详细内容可以到vue官方文档查看
指令
指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外)。指令的职责是:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
参数
- 绑定属性(v-bind,简写 : ),href 是参数
<a v-bind:href="url">...</a>
简写:<a :href="url">...</a>
- 添加事件(v-on,简写 @ ),事件名是参数
<a v-on:click="doSomething">...</a>
简写:<a @click="doSomething">...</a>
动态参数
<a v-bind:[attributeName]="url"> ... </a>
- 这里的 attributeName (动态属性)会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。
- 动态参数表达式有一些语法约束,因为某些字符,例如空格和引号,放在 HTML 特性名里无效。同样,在 DOM 中使用模板时需要回避大写键名。
修饰符
- 修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
- 使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
事件修饰符 .stop
.prevent
.capture
.self
.once
-
.passive
( .passive 修饰符尤其能够提升移动端的性能。)
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即元素自身触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成 -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>
- 不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。
计算属性与侦听属性
下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:
computed: {
now: function () {
return Date.now()
}
}
每调用一次now方法就会刷新时间:
methods: {
now: function () {
return Date.now()
}
}
计算属性:computed
方法:methods
侦听属性:watch(响应数据的变化)
- 计算属性是基于它们的响应式依赖进行缓存的,只有在相关响应式依赖发生改变时,它们才会重新求值。就是说如果相关的变量没有发生改变,多次访问计算属性,会立即返回之前的计算结果,而不必再次执行函数。
- 而每当触发重新渲染时,调用方法就会再次执行函数。
- 如果不希望有缓存,可以用方法来替代计算属性。
- Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当有一些数据需要随着其它数据变动而变动时,很容易滥用 watch ,然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。但当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
- computed 一般用于进行简单的计算,把模板上的简单计算逻辑放到 computed 中,简化模板,减轻模板负担。
- watch 更多用于更为复杂的计算,监听数据与数据之间的变动。还可以执行异步操作。
样式设置
绑定 class(v-bind:class)
-
对象
可以传给 v-bind:class 一个对象,动态地切换 class。
<div v-bind:class="{ active: isActive }"></div>
上面的语法表示active
这个 class 是否存在取决于数据属性isActive
的 truthiness
。isActive
为true
则显示active
样式表 。
data: {
isActive: true
}
v-bind:class 指令也可以与普通的 class 属性共存,
<div
class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>
如下data:
data: {
isActive: true,
hasError: false
}
结果渲染为:
<div class="static active"></div>
-
数组
可以把一个数组传给 v-bind:class,当成一个 class 列表来用。
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
渲染为:
<div class="active text-danger"></div>
如果你也想根据条件切换列表中的 class,可以用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
这样写将始终添加 errorClass
,但是只有在 isActive
是 truthy
时才添加 activeClass
。
不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
-
组件
当在一个自定义组件上使用 class 属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类不会被覆盖。
例如,如果你声明了这个组件:
Vue.component('my-component', {
template: '<p class="foo bar">Hi</p>'
})
然后在使用它的时候添加一些 class:
<my-component class="baz boo"></my-component>
HTML 将被渲染为:
<p class="foo bar baz boo">Hi</p>
对于带数据绑定 class 也同样适用:
<my-component v-bind:class="{ active: isActive }"></my-component>
当 isActive
为 truthy 时,HTML 将被渲染成为:
<p class="foo bar active">Hi</p>
绑定内联样式(v-bind:style)
-
对象
v-bind:style 的对象语法十分直观,看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
-
数组
v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[styleObject1, styleObject2]"></div>
条件渲染
v-if
,v-else
,v-else-if
,v-show
- v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
<h1 v-if="awesome">Vue is awesome!</h1>
也可以用 v-else 添加一个“else 块”:
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
- v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
- 类似于 v-else,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。
-
v-show 指令用于根据条件展示元素。
注意,v-show 不支持 <template> 元素,也不支持 v-else。
带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。
v-if (条件渲染)和 v-show (条件展示)
- v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
- v-if 也是惰性的:如果在初始渲染时条件为假,就什么也不做,直到条件第一次变为真时,才会开始渲染条件块。
- 而v-show不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
- 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,使用 v-show 更好;如果在运行时条件很少改变,使用 v-if 更好。
列表渲染
用 v-for 指令根据一组数组(或者一个对象)的选项列表进行渲染。v-for 指令需要使用 item in items (对象:value in object)形式的特殊语法,items 是源数据数组并且 item 是数组元素迭代的别名(items是数组名 item是数组项,value是属性值 object是对象名)。
变异方法 (mutation method),顾名思义,会改变被这些方法调用的原始数组,例如:push()
,pop()
,shift()
,unshift()
,splice()
,sort()
,reverse()
。相比之下,也有非变异方法 (non-mutating method) ,例如:filter()
,concat()
和 slice()
。这些不会改变原始数组,但总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组。
表单输入绑定
- 可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。
- v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:text 和 textarea 元素使用 value 属性和 input 事件;checkbox 和 radio 使用 checked 属性和 change 事件;select 字段将 value 作为 prop 并将 change 作为事件。
组件
- 组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。除了像 el 这样根实例特有的选项。
- 组件的复用,每用一次组件,就会有一个它的新实例被创建。
- 一个组件的 data 选项必须是一个函数:
data: function () {
return {
data : data
}
},
或者:data () {
return {
data : data
}
}
- 通过Vue.component注册组件(全局组件),components定义需使用的组件,通过 prop 向子组件传递数据, props 验证数据类型。
import ComponentA from './ComponentA.vue'//导入想使用的组件
import ComponentItems from './ComponentItems.vue'
export default {
props:{
title : String // name:type(名称 : 类型)
}
components: {
ComponentA, //等同于ComponentA : ComponentA
'component-items' : ComponentItems //在模板中引用<component-items />
},
// ...
}
- 每个组件只有一个根元素
<div id="App">
<h1>{{ App }}</h1>
<div><a :href = "url"></a></div>
</div>
- 自定义组件名
使用kebab-case(短横线分隔命名)和PascalCase(首字母大写命名),推荐字母全小写且使用短横线分隔命名。注意定义组件名和引用组件名一致。 - 单向数据流
所有的父子之间的 prop 都形成一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行;每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着我们不应该在一个子组件内部改变 prop。
type 可以是下列原生构造函数中的一个: - 类型检查
type 可以是以下原生构造函数中的一个:String
,Number
,Boolean
,Array
,Object
,Date
,Function
,Symbol
;type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。 - 特性继承
如果不希望组件的根元素继承特性,可以在组件的选项中设置inheritAttrs: false。配合实例的 $attrs 属性使用,该属性包含了传递给一个组件的特性名和特性值。有了 inheritAttrs: false 和 $attrs,就可以手动决定这些特性会被赋予哪个元素。
动态组件和异步组件
动态组件
- 在一个多标签的界面中使用 is 特性来切换不同的组件,当在这些组件之间切换的时候,有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。
- 每次切换新标签的时候,Vue 都创建了一个新的绑定 is 属性的对象的实例,有时候希望那些标签的组件实例能够在它们第一次被创建的时候缓存下来,可以用一个 <keep-alive> 元素将其动态组件包裹起来。
异步组件
- 在大型应用中,可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue 允许以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析已经定义的组件。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。
自定义事件
- 不同于组件和 prop,事件名不存在任何自动化的大小写转换。触发的事件名需要完全匹配监听这个事件所用的名称,即名称要完全一致。
- 不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或属性名,所以就没有理由使用 camelCase(驼峰命名) 或 PascalCase (首字母大写命名)了。
- 并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent,导致 myEvent 不可能被监听到。因此,推荐使用 kebab-case (短横线分隔命名)的事件名。
- .sync 修饰符
带有 .sync 修饰符的 v-bind 不能和表达式或对象字面量一起使用,不然是无效的。
插槽(v-slot指令)
- 如果组件内没有包含一个 <slot> 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
- v-slot 缩写, # ,和其它指令一样,该缩写只在其有参数的时候才可用。
<template #header>
<h1>Here might be a page title</h1>
</template>
- 编译作用域
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
过渡、动画
对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter。
过渡的类名
在进入/离开的过渡中,会有 6 个 class 切换。
-
v-enter
:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。 -
v-enter-active
:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。 -
v-enter-to
: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时v-enter
被移除),在过渡/动画完成之后移除。 -
v-leave
: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。 -
v-leave-active
:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。 -
v-leave-to
: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时v-leave
被删除),在过渡/动画完成之后移除。
动画
CSS 动画用法和 CSS 过渡相同,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。
过渡模式
-
in-out
:新元素先进行过渡,完成之后当前元素过渡离开。 -
out-in
:当前元素先进行过渡,完成之后新元素过渡进入。
可复用性
混入
- 混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
- 当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
- 据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
- 同名钩子函数将合并为一个数组,因此都将被调用,混入对象的钩子将在组件钩子之前被调用。
- 两个对象键名(方法)冲突时,取组件对象的键值对(方法)。
- 混入也可以进行全局注册。一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。
// mixin.js 抽取公共部分
export const myMixin = {
created: function() {
this.hello()
},
fetchApi(){
//内容
},
methods: {
hello: function() {
console.log('hello from mixin!')
this.fetchApi()
}
}
}
// ProductInfo.vue 需要引用 mixin 的组件
import {mymixin} from './mixin' //引入mixin文件
export default {
name: 'ProductInfo',
mixins:[mymixin], //可以把多个混入放到数组中
components: {
//组件
},
自定义指令
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
//注册局部指令,组件中也接受一个 directives 的选项
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 -
inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 -
update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。 -
componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。 -
unbind
:只调用一次,指令与元素解绑时调用。
指令钩子函数会被传入以下参数( 指令的参数可以是动态的):
-
el
:指令所绑定的元素,可以用来直接操作 DOM 。 -
binding
:一个对象,包含以下属性:-
name
:指令名,不包括v-
前缀。 -
value
:指令的绑定值。 -
oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。 -
expression
:字符串形式的指令表达式。 -
arg
:传给指令的参数,可选。 -
modifiers
:一个包含修饰符的对象。
-
-
vnode
:Vue 编译生成的虚拟节点。 -
oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
渲染函数
节点、树以及虚拟 DOM
- 当浏览器读到HTML代码时,它会建立一个相对应的“DOM 节点”树来保持追踪所有内容。
- 每个元素都是一个节点。每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就像家谱树一样,每个节点都可以有孩子节点 (也就是说每个部分可以包含其它的一些部分)。
- Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM。