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