本篇将介绍两个新的概念:混合、自定义指令。它们在构造大型项目时的可复用性上有不可或缺的地位。
mixins
mixins(混入)是一种分发vue组件中可复用功能的非常灵活的方式,接受的是一个对象数组数据格式。换种说法,mixins类似于java的继承,定义一个被继承的对象myMixin,让vue的构造继承myMixin,最后通过组件或实例初始化该vue构造。如果对vue构造、组件和实例概念不熟悉,可以浏览本系列第九篇文章。
mixins有两个特点:
1.当构造与混合对象的属性名称刚好相同时,取构造的键值对。
2.当同时包含钩子函数时,无论是构造还是混合对象的钩子函数,都会执行,而且混合对象的钩子函数优先执行。
(贴士)Vue.component不能直接使用mixins。
参考demo:
<div id="app"></div>
<script>
//局部混合,放到vue构造中mixins数组中
var myMixin = {
created: function() {
this.hello();
},
methods: {
hello: function() {
console.log('hello from mixin!' + this.pop)
},
fun: function() {
var vw = this;
console.log("fun from mixin!" + vw.pop);
}
},
data: function() {
return {
pop: "[mixData]"
}
},
}
var Component = Vue.extend({
mixins: [myMixin],
created: function() {
this.hello(); //调用myMixin对象的hello函数
},
data: function() {
return {
pop: "[extendData]" //当与myMixin对象有相同命名键值时,取构造的键值为准
}
},
template: "<p>template</p>",
methods: {
fun: function() {
var vw = this;
console.log("fun from extend!" + vw.pop); //当与myMixin对象有相同命名函数时,取构造的函数为准
}
}
})
var component = new Component()
component.fun(); // 构造与混合对象属性键值对相同时,取构造的键值对
component.$mount('#app'); // 挂载
</script>
运行结果:
混合对象还能通过全局注册,但是注意使用!如注册vue全局混合对象,一旦使用全局混合对象,将会影响到 所有 之后创建的 Vue 实例。
参考demo:
<div id="app"></div>
<script>
Vue.mixin({
created: function() {
var myOption = this.$options.myOption; //this.$options.key表示其自定义属性值,this.$el表示系统属性值
if(myOption) {
console.log(myOption);
}
}
})
new Vue({
myOption: 'hello!'
})
</script>
运行结果:打印 'hello'
自定义指令
自定义指令使用Vue.directive来定义,简单而言,就是从指令赋值中获取对添加该指令元素的操作说明,通过对操作的解析后按要求初始化该元素。
定义指令只要有5个钩子函数:
(1)bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
(2)inserted:被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
(3)update:所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。指令的值可能发生了改变也可能没有。
(4)componentUpdated:所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
(5)unbind:只调用一次,指令与元素解绑时调用。
这5个钩子函数有相同的入参:
(1)el:指令所绑定的元素,可以用来直接操作 DOM 。
(2)binding: 获取外界数值的对象
(3)vnode:vue 编译生成的虚拟节点
(4)oldVnode:上一个虚拟节点
参考demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="../js/libs/vue/2.4.2/vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-myorder:arg.a=value -->
<!-- arg用于对该指令区别类别 .a表示对该指令类别的修饰符,value类似于值对入参value -->
<!--如果你不需要arg.a,也可以直接写成 v-myorder=value -->
<p v-didemo:foo.a="msg">{{msg}}</p>
<button @click="change">改变msg</button>
</div>
</body>
<script>
Vue.directive("didemo", {
bind: function(el, binding, vnode) {
console.log(1, el, binding);
el.style.color = "red"; //设置文本字体颜色为红色
},
inserted: function(el, binding, vnode) {
console.log(2, el, binding);
},
update: function(el, binding, vnode) {
console.log(3, el, binding);
},
componentUpdated: function(el, binding, vnode) {
console.log(4, el, binding);
},
unbind: function(el, binding, vnode) {
console.log(5, el, binding);
}
});
var app = new Vue({
el: "#app",
data: {
msg: "hello world"
},
methods: {
change: function() {
this.msg = "i am change";
}
}
});
</script>
</html>
运行结果:
点击'改变msg'按钮后