官方解释
混入(mixin)提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
自己理解
将组件的公共逻辑或者配置提取出来,哪个组件需要用到时,直接将提取的这部分混入到组件内部即可。这样既可以减少代码冗杂度,也可以让后期维护起来更加容易。
需要注意的是:提取的是逻辑或者配置,而不是 HTML 代码和 CSS 代码。可以将 Mixin 简单理解为组件中的组件,Vue 组件化让代码复用性更高,那么组件与组件之间还有重复部分,就可以用 Mixin 再抽离一遍。
举例
当我们在使用 Vue 开发后台管理系统的时候,一定会使用到表格(用户数据,订单数据等等)来对数据进行展示,但是每一个表格的数据都需要向后台发送请求来获取表格的数据,而发送请求的逻辑代码如果每一个 Table 页面都去写一下的话,重复的代码就会有很多,这是我们就可以将发送请求获取数据的逻辑代码抽离出来,放到 Mixin 中,从而混入到需要获取数据的 Table 页面中。
export const TableListMixin = {
data() {
return {
// 数据源
dataSource: [],
// table加载状态
loading: false,
// 分页参数
ipagination: {
current: 1,
pageSize: 10,
currentTotal: 0,
pageSizeOptions: ['10', '20', '30'],
showTotal: (total, range) => {
return range[0] + "-" + range[1] + " 共" + total + "条"
},
showQuickJumper: true,
showSizeChanger: true,
total: 0,
onShowSizeChange: (current, pageSize) => this.handleSizeChange(current, pageSize),
},
}
},
loadData(arg) {
let that = this
if (!this.url.list) {
this.$message.error("请设置url.list属性!")
return
}
//加载数据 若传入参数1则加载第一页的内容
if (arg === 1) {
this.ipagination.current = 1;
}
var params = this.getQueryParams();//查询条件
// getQueryParams() 是获取查询条件的方法,此处就不具体列出了
this.loading = true;
if (this.isNoPageTotal) {
params.pageSize = 99999999
}
getAction(this.url.list, params).then((res) => {
if (res.success) {
this.dataSource = res.result.records || res.result;
if (res.result.total) {
this.ipagination.total = res.result.total;
} else {
this.ipagination.total = 0;
}
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.loading = false
})
},
}
在项目中的 Mixin 中添加了上述代码,我们就可以在 Table 页面获取数据的时候直接混入,并在 data 中添加一个对象:url: { list: '' } 对象,list 的值对应需要调用的接口地址即可。一套代码适用所有 Table 页面,是不是很方便?
定义 Mixin 也非常简单,它就是一个对象而已,只不过这个对象里面可以包含 Vue 组件中的一些常见配置,如 data、methods、created 等等。
在项目的 src 目录下新建 mixin 文件夹,然后新建 index.js 文件,该文件存放 Mixin 代码。
// src/mixin/index.js
export const mixins = {
data() {
return{}
},
computed: {},
created() {},
mounted() {},
methods: {}
}
可以看到 Mixin 非常简单,主要包含了一个 Vue 组件的常见的逻辑结构。
App 组件
mixins: [mixins]。答案是不会的。上一点使用 mixin 是在需要的时候在组件中引入,其实也可以在全局先把它注册好,这样就可以在任何组件中直接使用了。
// main.js
import Vue from 'vue'
import App from './App'
import { mixins } from './mixin/index.js'
Vue.mixin(mixins)
Vue.config.productionTip = false
new Vue({
render: (h) => h(App),
}).$mount('#app')
虽然全局引入很方便,但是不推荐使用。
请谨慎使用全局混入,因为它会影响每个单独创建的 Vue 实例(包括第三方组件)。大多数情况下,只应当应用于自定义选项,就像上面的示例一样。推荐将其作为插件发布,以避免重复应用混入。
先执行 mixin 中生命周期函数中的代码,然后执行组件内部的代码。组件中的 data 数据会覆盖 mixin 中的数据。当方法发生冲突时,默认调用的是组件的方法。提高代码复用性无需传递状态维护方便,只需要修改一个地方即可命名冲突滥用的话后期很难维护不好追溯源,排查问题稍显麻烦不能轻易的重复代码 Mixin 提供了方便的同时也带来了灾难,所以很多时候不建议滥用它,但是在有些场景下使用它又非常合适,这就要自己去判断了。所以在很多时候需要考虑用公共组件还是使用 Mixin 。