因为在项目中 mixins(混合)
特性使用频率是很高的 有必要熟练掌握
官方文档: mixins
实际项目中 一般都存在 列表(list) 这种很常见的使用场景
话再多都不如上demo
file: mixins/list.js
1 module.exports = { 2 data () { 3 return { 4 list: [], 5 page: 1, 6 limit: 15, 7 total: 0 8 } 9 }, 10 created () { 11 this.initList() 12 }, 13 watch: { 14 page: 'loadData' 15 }, 16 methods: { 17 /** 18 * 获取请求参数 默认只传递index(页码) limit(每页条数) 可以由调用方传递指定对象合并(或者覆盖)原参数 19 * @param params 20 * @returns {*} 21 */ 22 getParams (params) { 23 return Object.assign({ 24 index: this.page, 25 limit: this.limit 26 }, params) 27 }, 28 /** 29 * 加载更多 30 */ 31 loadMore () { 32 this.page++ 33 }, 34 /** 35 * 推送到list中 因为vue的监听特性 只能用push进行数据的添加 如果有特殊处理 通过传递一个filter来过滤数据 36 * @param list 37 * @param filter 38 */ 39 pushToList (list, filter) { 40 list.forEach((item) => { 41 if (typeof filter === 'function') { 42 this.list.push(filter(item)) 43 } else { 44 this.list.push(item) 45 } 46 }) 47 }, 48 /** 49 * 初始化列表 50 */ 51 initList () { 52 this.page = 1 53 this.list = [] 54 this.loadData() 55 }, 56 /** 57 * @overwrite 58 * 加载数据方法 用到该mixin的都应该重写该方法 否则无法实现加载数据 59 */ 60 loadData () { 61 // 每个列表自己的获取数据的方法需要重写 62 } 63 } 64 }解析
一个列表的基本属性
属性 作用或备注 list 列表 page 页码 limit 每页条数 total 总条数 基本方法
方法 作用或备注 initList() 初始化列表 loadData() 加载数据 loadMore() 加载更多 扩展方法[主要用于参数的处理和结果的处理]
方法 作用或备注 getParams() 获取HTTP请求参数 pushToList() 数据处理方法 每一个列表结构都具备的属性以及方法 可以放到
mixins
的声明中从这段代码中可以得知 加载了该
mixins
的组件会在创建之后执行一个initList
方法
顾名思义 就是初始化列表的方法1 created () { 2 this.initList() 3 }问题
但是问题来了 如果我的组件 不只是在初始化的时候使用
而是在使用了keep-alive
的应用下在route->data()
的钩子中执行初始化呢?1 route: { 2 data () { 3 this.initList() 4 } 5 }这时候你打开控制台 刷新页面 就会发现 第一次进入 初始化了两次
原因
因为
mixins
的合并策略当混合对象与组件包含同名选项时,这些选项将以适当的策略合并。例如,同名钩子函数被并入一个数组,因而都会被调用。另外,混合的钩子将在组件自己的钩子之前调用。
1 var mixin = { 2 created: function () { 3 console.log('mixin hook called') 4 } 5 } 6 new Vue({ 7 mixins: [mixin], 8 created: function () { 9 console.log('component hook called') 10 } 11 }) 12 // -> "mixin hook called" 13 // -> "component hook called"值为对象的选项,如 methods, components 和 directives 将合并到同一个对象内。如果键冲突则组件的选项优先。
1 var mixin = { 2 methods: { 3 foo: function () { 4 console.log('foo') 5 }, 6 conflicting: function () { 7 console.log('from mixin') 8 } 9 } 10 } 11 var vm = new Vue({ 12 mixins: [mixin], 13 methods: { 14 bar: function () { 15 console.log('bar') 16 }, 17 conflicting: function () { 18 console.log('from self') 19 } 20 } 21 }) 22 vm.foo() // -> "foo" 23 vm.bar() // -> "bar" 24 vm.conflicting() // -> "from self"注意 Vue.extend() 使用同样的合并策略。
所以即使你在引用的组件中 把
created
重写 也是被合并(两个都会执行) 因为合并的策略不同 导致了methods
可以被重写 而created
ready
等只会被合并解决方法
怎么解决?
读过阅读官方文档后我想你会有答案
我这里提供一个文档中提到的比较灵活的简单的方案
加一个自定义选项
1 created () { 2 let option = this.$options.doNotInit 3 if (!option) { 4 this.initList() 5 } 6 }通过该选项
doNotInit
来判断是否需要在组件创建完毕之后就初始化在调用该
mixins
的组件中 添加这么一个选项 就可以让组件不执行初始化方法而是通过
route->data()
钩子来控制列表的初始化调用
file: anyVueComponent.vue
1 import List from 'path/mixins/list' 2 export default{ 3 mixins: [List], 4 data () { 5 return { 6 // 除列表外额外的属性 7 } 8 }, 9 methods: { 10 loadData () { 11 this.$http.post(yourApiUrl, this.getParams()).then((res) => { 12 // do somethings 13 }) 14 } 15 }, 16 doNotInit: true, 17 route: { 18 data () { 19 this.initList() 20 } 21 } 22 }说到底 仔细阅读Vue文档 项目中遇到的绝大多数问题 都能迎刃而解~