前言

Mixins是一种分发Vue组件中可复用功能的非常灵活的一种方式。

那么页面的风格不用,但是执行的方法和需要的数据类似,我们是选择每个都写呢还是提取出公共部分呢?

基础实例

我们有一对不同的组件,它们的作用是切换一个状态布尔值,一个模态框和一个提示框。这些提示框和模态框除了在功能上,没有其他共同点:它们看起来不一样,用法不一样,但是逻辑一样。

// 模态框
const Modal = {
template: '#modal',
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
},
components: {
appChild: Child
}
}
// 提示框
const Tooltip = {
template: '#tooltip',
data() {
return {
isShowing: false
}
},
methods: {
toggleShow() {
this.isShowing = !this.isShowing;
}
},
components: {
appChild: Child
}
}

解决办法如下:

const toggle = {
data () {
isshowing: false
},
methods: {
toggleShow() {
this.isshowing = !this.isshowing
}
}
}

// 下面即可使用了
// mixins: [变量名]

const Modal = {
template: '#modal',
mixins: [toggle],
components: {
appChild: Child
}
};

const Tooltip = {
template: '#tooltip',
mixins: [toggle],
components: {
appChild: Child
}
};

如果你是以vue-cli创建的项目来写,可以这样

// mixin.js

export const toggle = {
data () {
isshowing: false
},
methods: {
toggleShow() {
this.isshowing = !this.isshowing
}
}
}
// modal.vue
// 将mixin引入该组件,就可以直接使用 toggleShow() 了
import {mixin} from '../mixin.js'

export default {
mixins: [mixin],
mounted () {

}
}
// tooltip组件同上

合并

当组件和混入对象含有同名选项时,这些选项将以恰当的方式混合。

数据对象内

mixin的数据对象和组件的数据发生冲突时以组件数据优先。

var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}

new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "goodbye", foo: "abc", bar: "def" }
}
})

钩子函数

同名钩子函数将会混合为一个数组,都将被调用到,但是混入对象的钩子将在组件自身钩子之前调用。

var mixin = {
created: function () {
console.log('混入对象的钩子被调用')
}
}

new Vue({
mixins: [mixin],
created: function () {
console.log('组件钩子被调用')
}
})

// => "混入对象的钩子被调用"
// => "组件钩子被调用"

值为对象的选项

值为对象的选项,例如 methods, components 和 directives,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。

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() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"

全局混入

全局混合被注册到了每个单一组件上。因此,它们的使用场景极其有限并且要非常的小心。一个我能想到的用途就是它像一个插件,你需要赋予它访问所有东西的权限。但即使在这种情况下,也不建议这么做,还是十分危险的。

Vue.mixin({
mounted() {
console.log("我是mixin");
}
})

new Vue({
...
})

此个console.log将会出现在每个组件上。这种情况还不算坏(除了控制台上有多余的输出),但如果它被错误的使用,它是十分有害的。

一个使用合理的例子

// 为自定义的选项 'myOption' 注入一个处理器。
Vue.mixin({
created: function () {
var myOption = this.$options.myOption
if (myOption) {
console.log(myOption)
}
}
})

new Vue({
myOption: 'hello!'
})
// => "hello!"

总结

混合对于封装一小段想要复用的代码来讲是有用的。对你来说它们当然不是唯一可行的。混合很好,它不需要传递状态,但是这种模式当然也可能会被滥用。所以我们还是需要仔细斟酌使用喽!!

参考链接

vue文档