在项目中 mixins
(混合)特性使用频率是很高的 有必要熟练掌握
官网传送门:mixins
# 简介
混入(mixins
)是一种分发Vue组件中可复用功能的非常灵活的方式,它的存在使得开发者们可以定义一部分公用的属性或方法,然后混入到各个组件内部使用,提高了可维护性。
一个混入自身以一个对象的形式存在,如var mixin = { }
,它可以包含任意组件选项。在调用方中,调用混入对象使用mixins: []
,接收一个混入对象的数组,也就是说可以一次混入多个混入对象。
# 混入选项合并
当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项中。
先看案例再理解
'# file: mixins/welcome.js'
export const Welcome = {
created: {
this.initPage();
},
methods: {
initPage() {
this.$toast('icon-welcome', '正在进入系统,请稍后...')
}
}
}
在组件中混入如上混入对象
import { Welcome } from '../assets/js/mixins/welcome'
export default {
name: 'AnyComponent',
mixins: [ Welcome ],
data () {
return {
greet: '正在进入业务系统,请稍后...'
}
},
created: {
this.initPage()
},
methods: {
initPage() {
this.$toast('icon-welcome', this.greet)
}
}
}
----------------------
# 执行结果
正在进入业务系统,请稍后...
正在进入业务系统,请稍后...
对此结果或许会感到疑惑,那是因为有如下混入规则:
- data选项在混入时,数据对象在内部会进行递归合并,当发生冲突时,以组件数据优先
- 同名钩子函数混合为一个数组,两个钩子函数内部的逻辑都会被执行,且混入的比组件的先调用
- 值为对象的选项如
methods, components, directives
将被 混合为同一个对象。冲突取组件键值对 - 自定义的混入策略,见后续
再来理解以上案例,created
钩子混入后两个方法调用都会执行,而methods
因为混入时键冲突以组件为主,因此有了以上输出。
# 自定义混入策略
如果想让自定义选项使用自定义逻辑混入合并,可以向Vue.config.optionMessageStrategies
添加一个函数,例如自定义选项名为myOption
则
Vue.config.optionMessageStrategies.myOption = function (toVal, fromVal) {
// return mergeVal
}
对于大多数自定义的对象型选项来说,直接复用methods
的即可
var strategies = Vue.config.optionMergeStrategies
strategies.myOption = strategies.methods
举一个vuex的混入案例如下,复用了computed
的混入规则
const merge = Vue.config.optionMergeStrategies.computed
Vue.config.optionMergeStrategies.vuex = function (toVal, fromVal) {
if (!toVal) return fromVal
if (!fromVal) return toVal
return {
getters: merge(toVal.getters, fromVal.getters),
state: merge(toVal.state, fromVal.state),
actions: merge(toVal.actions, fromVal.actions)
}
}
# 经典案例高级用法
实际项目中一般都会存在 列表(List)
这种很常见的案例,本文将介绍怎么利用mixin
来实现一个能高复用的混入模型,并拆解分析各个步骤要点
$ 代码及设计
- file: assets/mixins/list.js
module.exports = {
data () {
return {
list: [], // 列表数据
page: 1, // 当前页码
limit: 10, // 单页条数
total: 0 // 总条数
}
},
created () {
this.initList()
},
watch: {
page: 'loadData'
},
methods: {
/**
* @func 获取请求参数 默认只传递index, limit。也可以由外部构建合并参数
* @param params
* @returns {*}
*/
getparams (params) {
return Object.assign({
index: this.page,
limit: this.limit
}, params)
},
/**
* @func 查询结果压入list,注意Vue监听的特性,更新数组应用push,有格式需要处理则传入filter函数
* @param list-加载更多返回的数据列表, filter-数据过滤函数
*/
pushToList (list, filter) {
list.forEach(item => {
let it = typeof filter == 'function' ? filter(item) : item
this.list.push(it)
})
},
/**
* @func 加载更多
*/
loadMore () {
this.page++
},
/**
* @func 初始化列表
* /
initList () {
this.page = 1
this.list = []
this.loadData()
},
/**
* @overwrite
* @func 加载数据方法,组件中必须根据自己需要重写该方法,否则无法加载数据
*/
loadData () {
// please overwrite me
}
}
}
$ API 及 README
- 一个列表的基本属性
属性 | 作用或备注 |
---|---|
list | 列表 |
page | 页码 |
limit | 每页条数 |
total | 总条数 |
- 基本方法
方法 | 作用或备注 |
---|---|
initList() | 初始化列表 |
loadData() | 加载数据(组件请重写) |
loadMore() | 加载更多 |
- 扩展方法:主要用于参数或结果的处理
方法 | 作用或备注 |
---|---|
getParams() | 获取HTTP请求参数 |
pushToList() | 数据处理方法,新数据入队列 |
每一个列表结构都具备的属性以及方法 可以放到mixins
的声明中
$ 提示:vue监听数组变化
Vue观察数组变化主要通过以下7个方法(push、pop、shift、unshift、splice、sort、reverse
),通过prototype
添加或下标方式将不能成功被捕获
$ 问题:非初始化情况下使用
在keep-alive
的应用下使用route-->data()
的钩子中执行初始化,会发现初始化了两次
route: {
data () {
this.initList()
}
}
$ 原因:mixin
合并策略导致
因为混入规则,即使你在引用的组件中,把created
重写,也是两个都会执行),因为合并的策略不同导致了 methods
可以被重写 而created ready
等只会被合并。
$ 解决办法: 自定义选项
自定义选项doNotInit
,通过该选项来判断是否需要在组件创建完毕之后就初始化
在调用该mixins
的组件中 添加这么一个选项,就可以让组件判断通过create初始化,还是通过route->data()钩子来初始化
created () {
let option = this.$options.doNotInit
if (!option) {
this.initList()
}
}
$ 使用(调用)混入
- file: anyVueCompontent.vue
import List from './../assets/mixins/list'
export default {
mixins: [ List ],
data () {
return {
// 除列表外其他属性
}
},
methods: {
loadData () {
this.$http.post(yourApiUrl, this.getParams()).then(res => {
// TODO: some logic
})
}
},
doNotInit: true, // 指定为created不执行初始化
route: {
data () {
this.initList()
}
}
}