混入(mixin)的使用非常简单,其实我原本打算直接写插件(plugin)的,但考虑到插件的使用范围也包括混入和自定义指令,还是先讲讲这两个的基本概念。
混入在我看来,就是给组件加上一些通用的属性和方法。比如说我们项目有很多个页面是要展示分页列表的,那页面组件都会包含当前页、每页记录、总记录数、总页数这些属性、还有页面增删查改操作的函数等等,其中有很多是完全一样,或者具备一定可复用性的。如果每个页面都搞这么一大坨,不单写起来繁琐,看起来也很乱。要是碰上不同的人开发,变量名定义还不一样,可读性可维护性就很差。所以我们想要有个东西能把这些共同的部分提取出来,这里面就要用到混入的概念。项目中如何使用大家可以参考一些开源的后台管理系统,比如jeecg的前端就用了混入。
先利用vue-cli建一个项目test_mixin。不懂建的参考我第一篇vue文章《Vue学习(一)——组件基础》。
现在我们假设我们项目的每个组件created方法都调用console.log('create'),并且每个组件都有一个hello方法,另外还有两个属性current、pageSize。
创建目录src/mixin,并在该目录下新建文件mixinHello.js:
export const mixinHello = {data(){return{current: 1,pageSize: 10}},created: function () {console.log('create')},methods: {hello: function () {console.log('hello from mixin!')console.log('current:' + this.current)console.log('pageSize:' + this.pageSize)}}
}
代码很简单,就是像我们这节开始说的那样,定义好current、pageSize属性,created方法、hello方法。接着我们在src/components目录下创建一个自定义按钮组件myBtn,并把混入加到其中:
然后我们修改App.vue,引入muBtn
执行run server,访问localhost:8080,如图:
我们点F12打开开发者工具,刷新页面,可以看到打印出create,证明调用了mixinHello的created方法:
然后点击按钮,打印出hello方法执行的内容。
当然如果这些方法和属性仅仅用在一个组件上,显然是没必要使用混入。混入的意义在于复用,如果很多组件都需要用到这些方法和属性,使用混入就恰到好处了。
混入在复用时可以节省很多功夫,但是有衍生出另一个问题,如果我们在组件里面定义了名称相同的方法或者属性,执行的时候会用哪个?我们在src/components目录下创建零一个自定义按钮组件myBtnMerge.vue
修改App.vue,注释掉myBtn,加上myBtnMerge
运行项目后,刷新网页,然后点击按钮,看到F12的输出:
这里我们有三个结论:
1、对于钩子函数,比如created、mounted、destroyed一类,组件自定义的方法和混入的方法同名时,会合并,并且混入的方法先于组件自定义的调用。
2、对于组件自定义的数据对象,和混入对象合并后,如果存在冲突的属性,则以组件自定义的优先。
3、对于methods、components 和 directives这一类,组件自定义的与混入的内部键值存在冲突时,以组件自定义的优先。
看起来这个有点像面向对象的继承。钩子函数像构造函数。其他则类似成员属性和成员方法。
如果不想使用默认的合并策略,混入还可以自定义合并的策略。具体实现读者可以自行搜索“optionMergeStrategies”这个关键词。
混入的使用在我看来有点像面向对象里面的继承。好处是相同的属性和方法没必要重复写很多遍。尤其是做项目时,每个分页都要写一堆方法非常繁琐。当然对于钩子函数还是要谨慎使用混入,因为即使组件自定义了钩子函数,也不会覆盖混入的钩子函数。