Vue-5个进阶构造属性
本章介绍:directive、mixin、extend、provide&inject这5个Vue的进阶构造属性。
Directive-指令
-
什么是指令?
其实之前我们就已经学习了指令,如:
v-if
、v-for
,类似这些以 v- 开头的就是指令,而v-if
、v-for
这些属于内置指令,除此之外我们还可以自定义指令。 -
全局自定义指令
全局自定义指令:在全局作用域下自定义指令,同时这个指令也能够用于全局,即任何组件都能够使用这个全局指令。如要声明多个全局指令,多次调用
Vue.directive
// 声明全局指令,注意在全局作用域下 Vue.directive('x',directiveOptions) // 使用全局指令,在任何组件中都可以使用 v-x <myComponent v-x ></myComponent>
-
局部自定义指令
局部自定义指令:在某个组件Vue对象下进行声明,只能在该Vue组件的实例中使用。注意局部声明时的 directives。
// 声明局部指令 <script> export default { ... directives:{ "x":directiveOptions, "y":directiveOptions } } </script> // 只能在该组件中使用局部指令 <template> <div v-x v-y></div> </template>
-
directiveOptions
在上面的声明中,我们只是演示了指令的声明,并没有研究如何赋予指令功能,而指令的功能是通过directiveOptions中的5个钩子函数来实现的。
- directiveOptions中的5个钩子函数:
- bind:可以看成Vue中的created函数,即:当使用该指令的VNode(虚拟DOM)加载到内存中时执行的钩子函数。
- inserted:被绑定元素插入父节点时调用。
- update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。
- componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
- 钩子函数被传入的4个参数:(el,binding,vnode,oldVnode)
- 第一个参数el:指令所绑定的元素,可以用来直接操作DOM。
- 第二个参数binding:这是一个对象,包含下列属性
- name:指令名,不包括
v-
前缀 - value:指令的绑定值,如:
v-on:click='sayhi'
,这个sayhi就是指令绑定值。 - oldValue:指令绑定的前一个值,仅在
update
和componentUpdated
钩子中可用。无论值是否改变都可用。 - expression:字符串形式的指令表达式,如:
v-on:click='sayhi'
,这里'sayhi'
就是指令表达式。 - arg:传给指令的参数,如:
v-on:click='sayhi'
,这个click
就是传给指令的参数。 - modifiers:一个包含修饰符的对象。 例如:
v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
- name:指令名,不包括
- 第三个参数vnode:Vue 编译生成的虚拟节点。
- 第四个参数oldVnode:Vue 编译生成的上一个虚拟节点。
- directiveOptions中的5个钩子函数:
-
使用directiveOptions完整声明一个指令
下面我们通过一个小例子,来简单实现Vue内置指令
v-on
的绑定事件的功能。new Vue({ directives: { "myOn": { inserted: (el, info) => { el.addEventListener(info.arg, info.value) } } } })
-
指令的作用以及使用场景
Vue组件/实例的主要用于数据绑定、事件监听、DOM更新,而指令的作用主要是完成原生DOM操作。
当我们需要重复多次相同的原生DOM操作,或者是进行一些比较复杂的原生DOM操作时,可以借助指令来完成。
mixins-组合
-
什么是mixins?
简单来说就是“复制”。有时候我们需要使用多次相同的组件,这些组件的代码几乎一样,为了节省代码量,我们可以将这些相同的部分提取出来,然后通过mixin组合到各自组件中。mixins中的操作会合并到其他Vue实例中后,当作一个整体运行:比如:mixin中没有某个变量,但是其它Vue实例中有,这种情况下并不会报错,因是先合并了才运行。
-
mixins的意义
mixins可以减少data、methods、钩子的重复使用。
-
mixins的使用
// 相同部分提取 log.js export default { data(){ return { a:'a' } }, methods:{ hw:function(){ console.log('helloWorld') } }, created:function(){ console.log('created') } }
// 在组件中使用提取的部分 myComponent.vue import log from './log.js' export default { // 这里是个数组,说明可以使用多个mixins mixins:[log], data(){ return { b:'b' } } } // 此时,这组件就可以使用mixins中的 a数据 ,hw方法 ,created ,以及自身的 b数据
-
mixins是智能合并的
相同data当前实例优先级更高,而相同的钩子函数则会把两边的操作都合并起来。
-
全局mixin
Vue.mixin({mixin对象})
注意:全局mixin声明时没有s(mixin)。使用全局mixin后,所有的组件包括App.vue都会默认合并这个全局mixin,所以不建议使用全局mixin。
extends-继承
-
extends的作用
extends的作用和mixins一样,但是形式不同。
-
extends的使用
1.局部extends的使用
// 声明扩展内容 const myVue = {} // 使用 export default { // 注意这里不是数组 extends:myVue, data(){ return {} } }
-
全局extends的使用
// 全局声明 const myVue = Vue.extend({扩展内容}) // 继承式声明Vue实例 new myVue({vueOptions})
-
extends与extends&mixins
extends声明的扩展内容还能够使用extends和mixins。
import log from './log.js' // mixin const com1 = {} const com2 = { extends:com1, mixins:[log] }
-
provide提供&inject注入
-
什么是provide和inject?
上级组件可以通过provide传递data与method,而下级组件可以通过inject获取上级组件传递的data与method。
provide和inject能够大范围传递data和methods
-
provide和inject的使用方法
// 上级组件 export default { data(){ return { n:'n'} }, methods:{ add(){ console.log('add') } }, provide(){ return { n:this.n, add:this.add } } } // 下级组件 // 我们就可以在下级组件中,使用n与add export default { inject:['n','add'] }
-
provide和inject使用细节
传递的data时,父组件把自身data的地址复制了一份传递了,子组件能够获取data的值,但如果想在子组件中修改父组件的某些data(简单类型如Number、String)是不允许的,因为我们修改的只是复制的变量的值。但是我们可以通过在子组件中调用父组件传递过里啊的method来修改父组件的data,因为传递过来的method内部关联的是父组件的data。
但是如果父组件provide的data是一个对象,由于上级组件复制的是一个地址,所以子组件访问的也是同一个对象,那么在子组件中是能够修改这个对象,进而影响到父组件的。不推荐传递一个provide一个对象,因为如果都使用这个方法,那么在组件较多的情况下很难确定那个对象当前是出于什么状态。