- 指令
内置指令
v-bind指令
- 主要用于动态绑定DOM元素属性。
v-bind 可简写为 :
eg:<image v-bind:src=’avatar’/> --> <image :src=’avatar’/>
- 有三种修饰符:
- .sync
用于组件props属性,进行双向绑定,即父组件绑定传递给子组件的值,无论在哪个组件进行修改,其他组件的值会随之更新。
<my-child :parent.sync = ‘parent’></my-child>
父组件实例vm.parent将通过prop选项传递给<my-child>子组件,my-child组件构造函数需要定义选项props:[‘parent’],便可通过自身实例vm.parent获取父组件传递的数据。
- .once
同样作用于props属性。进行单次绑定,且将数据传递给子组件后,子组件单独维护这份数据。父组件数据发生变化,不影响子组件中的数据。
- .camel
将绑定的特性名称转回驼峰命名。
eg: <svg width = ‘400’ :view-box.camel=’viewBox’></svg>
<svg width = ‘400’ viewBox=’....’></svg>
在vue2.0中,废弃了.sync和.once,规定组件之间只能单向传递。
v-modle指令
在2.2.3小节表单控件中有过说明。
对表单元素进行双向绑定,在修改表单数据的同时,实例vm中的数据也同时被更新。主要用于input,select,textarea标签中。
v-if/v-else/v-show指令
根据条件展示对应模板内容。
v-if和v-show的区别:
v-if在条件为false时不进行模板编译,而v-show则会在模板编译好后根据条件进行元素隐藏。
v-if的切换消耗比v-show高。但初始条件为false时候,v-if的初始渲染要快。
v-for指令
也是用于模板渲染。
<ul>
<li v-for=’(index,item) in items’></li>
<p>{{item.name}}</p>
.....
</ul>
该指令在Vue.js 2.0的调整
- 参数顺序变化
(index, item)--> (item, index)
- v-bind:key
<div v-for=”item in items” tranck-by=”id”>
↓
<div v-for=”item in tiems” v-bind:key=”item.id”>
- n in 10
v-for = “n in 10” 原来n从0~9,变为1~10
v-on指令
用于事件绑定。
<button v-on:click=’onClick’></button>
简写如下:
<button @click=’onClick’></button>
在Vue.js 2.0中,v-on指令只监听自定义事件。如果要监听原生事件,需要使用修饰符.native
<my-component v-on:click.native=”onClick”></my-component>
v-text指令
v-text的参数类型为string。
作用:更新元素的textContent。
eg: <span v-text=”msg”></span>
{{}} 文本插值本身也会被编译成textNode的一个v-text指令。
与{{}}差异:v-text需要绑定在某个元素上,能避免未编译前的闪现问题。
v-HTML指令
参数类型也为string。接受的字符串不会进行编译等操作,按普通的html处理。
作用:更新元素的innerHTML。
eg: <div v-HTML=”HTML”></div>
{{{}}} 插值也会编译为节点的v-HTML指令。
与{{{}}}差异:v-HTML也需要绑定在某个元素上且能避免编译前的闪现问题。
v-el指令
为DOM元素注册了一个索引。
<div v-el:demo>there is a el demo</div>
通过如下方式调用元素获取元素中的文本内容:
vm.$els.demo.innerText 或在vm内部通过this调用。
由于HTML不区分大小写。在v-el中使用驼峰式命名,系统会自动转成小写。但可使用“-”连接期望的大写字母。
<div v-el:camelCase>There is camelcase</div>
<div v-el:camel-case>There is a camelcase</div>
vm.$els.camelcase.innerText
vm.$els.camelCase.innerText
分别能访问到上下两个元素中的内容
v-ref指令
v-ref与v-el类似,v-ref用于子组件。实例可通过$refs访问子组件。
<message v-ref:title content=”title”></message>
var Message = Vue.extend({
props:[‘content’],
Template:’<h1>{{content}}</h1>’
});
Vue.component(‘message’, Message);
v-pre指令
跳过编译这个元素和子元素,显示原始的{{}}Mustache标签,用来减少编译时间。
<div v-pre>{{uncompiled}}</div>
var vm = new Vue({
el:’#app’,
Data:{
uncompiled:’There is an uncompiled element.’
}
});
最后输出
<div v-pre>{{uncompiled}}</div>
v-cloak指令
防止页面加载时出现 vuejs 的变量名而设计的,解决屏幕闪动。
v-once指令
标明元素或组件只渲染一次。
<span v-once>{{msg}}</span>
<my-component v-once:msg=’msg’></my-component>
自定义指令基础
Vue.js提供了方法可以注册自定义指令,封装对DOM元素的中的处理行为,提高代码复用率。
指令的注册
可通过Vue.directive(id, definition)方法注册一个全局自定义指令。
id:指令的唯一标识。
定义对象:指令的相关属性及钩子函数。
eg: Vue.directive(‘glboal-directive’, definition);
<div v-glboal-directive></div>
可通过在组件的directives选项注册一个局部的自定义指令。
eg:
var comp = Vue.extend({
directives:{
‘localDirective’:{}
}
});
注册后该指令就能在当前组件内通过v-local-directive的方式调用。无法被其他组件调用。
指令的定义对象
定义对象主要包含三个钩子函数:bind,update和unbind。
bind:只被调用一次,在指令第一次绑定元素上时调用。
update:指令在bind之后以初始值为参数进行第一次调用,之后每次当绑定值发生变化是调用。
unbind:指令从元素上解绑时调用,只调用一次。
<div v-if=”isExist” v-my-directive=”param”></div>
Vue.directive(‘my-directive’, {
bind:function(){
console.log(‘bind’, arguments);
},
update:function(newValue, oldValue){
console.log(‘update’, newValue, oldValue);
},
unbind:function(){
console.log(‘unbind’, arguments);
}
})
var vm = new Vue({
el:’#app’,
data:{
param: ‘first’,
isExist:true
}
});
// todo 例子
如果只需要update函数,可直接传入一个函数代替定制对象:
Vue.directive(‘’, function(value){
//......
});
除过上面指令绑定data中的param属性,还可直接绑定字符串常量,或使用字面修饰符。但update方法将只调用一次,因为普通字符串不能响应数据变化。
<div v-my-directive=”’constant string’”></div>
<div v-my-directive.literal=”constant string”></div>
指令也能接受对象字面量或任意合法的JavaScript表达式。
<div v-my-directive=”{ title : ’Vue.js’, author : ’You’ }”></div>
<div v-my-directive=”isExist ? ‘yes’ : ‘no’”>
指令实例属性
el:指令绑定的元素。
vm:该指令的上下文ViewModle,可以为new Vue()的实例,也可以为组件实例。
expression:指令的表达式,不包括参数和过滤器。
arg:指令的参数
name:指令的名字,不包括v-前缀
modifiers:一个对象,包含指令的修饰符。
descriptor:一个对象,包含指令的解析结果。
<div v-my-msg:console.log=”content”></div>
Vue.directive(‘my-msg’, {
bind:function(){
console.log(‘~~~~~bind~~~~’);
console.log(‘el’, this.el);
console.log(‘name’, this.name);
console.log(‘vm’, this.vm);
console.log(‘expression’, this.expression);
console.log(‘arg’, this.arg);
console.log(‘modifiers’, this.modifiers);
console.log(‘descriptor’, this.descriptor);
},
update:function(newValue, oldValue){
var keys = Object.keys(this.modifiers);
window[this.arg][keys[0]](newValue);
},
unbind:function(){
}
});
var vm = new Vue({
el:’#app’,
data:{
content:’there is the content’
}
});
元素指令
普通指令需要绑定在某个具体的DOM元素上,但元素指令可以单独存在。从使用方式上更像一个组件,但本身内部的实例属性和钩子函数是和指令一致的。
元素指令使用方式 eg:<my-directive></my-directive>
元素指令的注册方式和普通指令类似,也有全局注册和局部注册两种。
Vue.elementDirective(‘my-ele-directive’); //全局注册方式
var Comp = Vue.extend({ //局部注册,仅限该组件内使用
...///
elementDirectives:{
‘eleDirective’:{}
}
});
Vue.component(‘comp’, Comp);
指令的高级选项
Vue.js指令定义对象中除了钩子函数外,还有一些其他选项。
params
定义对象中可以接受一个params数组。编译器将自动提取自定义指令绑定元素上的这些属性。
<div v-my-advance-directive a=”paramA”></div>
Vue.directive(‘my-advance-directive’, {
params:[‘a’],
bind:function(){
console.log(‘params’, this.params);
}
});
上面的例子是直接传入数值。
params支持绑定动态数据,并可以设定一个watcher监听,当数据变化时,会调用这个回调函数。
<div v-my-advance-directive v-bind:a-”a”></div>
Vue.directive(‘my-advance-directive’, {
params:[‘a’],
paramWatchers:{
a:function(val, oldVal){
console.log(‘watcher: ’, val, oldVal);
}
},
bind:function(){
console.log(‘params’, this.params);
}
});
var vm = new Vue({
el: ‘#app’,
data:{
a : ‘dynamitc data’
}
});
deep
监听对象内部发生的变化。
<div v-my-deep-directive=”obj”></div>
<div v-my-nodeep-directive=”obj”></div>
Vue.directivce(‘my-deep-directive’, {
deep:true,
update:function(newVal, oldVal){
console.log(‘deep’, newVal.a.b);
}
});
Vue.directivce(‘my-nodeep-directive’, {
update:function(newVal, oldVal){
console.log(‘deep’, newVal.a.b);
}
});
var vm = new Vue({
el:’#app’,
data:{
obj:{
a:{
b:’inner’
}
}
}
});
在控制台中输入vm.obj.a.b=’inner changed’,只有my-deep-directive调用update函数。
twoWay
需要向Vue实例写回数据时,在定义对象中使用twoWay:true,这样可以在指令中使用this.set(value)来写回数据。
<input v-my-twoWay-directive=”param”/>
Vue.directivce(‘my-twoWay-directive’, {
twoWay:true,
bind:function(){
this.handler=function(){
console.log(‘value changed’, this.el.value);
this.set(this.el.value)
}.bind(this)
this.el.addEventListener(‘input’, this.handler)
},
unbind:function(){
this.el.removeEventListener(‘input’, this.handler)
}
});
var vm = new Vue({
el:’#app’,
data:{
param:’first’
}
});
acceptStatement
允许自定义指令接受内联语句,同时update函数接收的值是一个函数,在调用该函数时,它将在所属实例作用域内运行。
<div v-my-directive=”i++”></div>
Vue.directive(‘my-directive’, {
acceptStatement:true,
update: function(fn){
}
})
Var vm = new Vue({
el:’#app’,
data:{
i:0
}
});
terminal
阻止Vue.js遍历这个元素及其内部元素,并由该指令本身去编译绑定元素及其内部元素。v-if和v-for都是terminal指令。
priority
指定指令的优先级。普通指令默认为1000。termial指令为2000。
同一元素上优先级高的比其他先处理,相同优先级按出现顺序处理。
指令在Vue.js 2.0中的变化
Vue.js 2.0中的指令功能更加单一,很多和组件重复的功能和作用都进行了删除,指令也更专注与本身作用域的操作,而尽量不影响指令外的DOM元素及数据。
新的钩子函数
钩子函数增加了一个componentUpdated,当整个组件都完成了update状态后即所有DOM都更新后调用该钩子函数。
钩子函数实例和参数变化
Vue.js2.0 取消了指令实例这个概念。即不能用this。指令的相关属性均通过参数的形式传递给钩子函数。
update函数触发变化
- 指令绑定bind函数执行后不能直接调用update函数
- 只要组件发生重绘,无论指令接受的值是否发生变化,均会调用update函数。
参数binding对象
钩子函数接受的参数binding对象为不可更改。