组件继承合并--Vue.mixin

我们在用Vue进行前端开发的时候,往往会遇到有很多个组件内,他们都有类似的data,类似的方法。这些大量重复的代码,如果正常编写出来,代码既不美观也不优雅,而且看起来也相当复杂。所以vue官方提供了一个极其好用的方式来解决这个问题

那就是mixin

先来看看官方的介绍

混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

在Java开发中 如果我们遇到两个类有大量相似代码的时候,我们通常会定义一个父类,来讲这些重复代码写在一起,然后再让这两个类来继承父类的代码和方法。

class Animal{
    run(){}
}
class Person extends Animal{
    //run(){}
}
class Dog extends Animal{
    //run(){}
}

而在Vue中,每个组件export出来的是对象,所以不能像类那样继承,于是Vue提供了类似于类的继承的方法 mixin

使用方法,在这里贴上自己项目的部分代码。

定义一个mixin.js 文件

import {debounce} from './utils';
​
export const itemListenerMixin = {
    data(){
        return {
            itemImgListener: null,
        }
    },
    methods:{
​
    },
    mounted(){
        let newRefresh = debounce(this.$refs.scroll.refresh, 100)
​
        this.itemImgListener = () => {
            newRefresh()
        }
​
        this.$bus.$on('itemImgLoad', this.itemImgListener)
        console.log("我是混入的东西")
    }
}

mixin 里就跟一个正常的Vue的组件没有任何的区别,可以定义data,methods,生命周期函数等等。跟Java里面的父类和子类完全一样。只是调用的方法不一样而已。

两个调用mixin.js的组件

Detail.vue

import {itemListenerMixin} from "common/mixin";
​
mixins: [itemListenerMixin],
//其余代码均省略

Home.vue

import {itemListenerMixin} from "common/mixin";
​
mixins: [itemListenerMixin],
//其余代码均省略

只需要这样一小段代码,就可以调用到mixin.js 内定义的组件了。

而且在两个组件内,作用完全一样

当我们在组件上应用Mixin的时候,有可能组件与Mixin中都定义了相同的生命周期钩子,这时候钩子的执行顺序的问题凸显了出来。默认Mixin上会首先被注册,组件上的接着注册,这样我们就可以在组件中按需要重写Mixin中的语句。组件拥有最终发言权。当发生冲突并且这个组件就不得不“决定”哪个胜出的时候,这一点就显得特别重要,否则,所有的东西都被放在一个数组当中执行,Mixin将要被先推入数组,其次才是组件。

const myMixin = {
    mounted() {
    console.log('mixin!')
    }
}
​
new Vue({
    el: '#app',
    mixins: [myMixin],
    mounted() {
    console.log('Vue instance!')
    }
});
​
  //Output in console
  > mixin!
  > Vue instance!
//mixin
const myMixin = {
    methods: {
    sayHello: function() {
        console.log('mixin!')
    }
},
    mounted() {
        this.sayHello()
    }
}
​
//vue instance or component
new Vue({
    el: '#app',
    mixins: [myMixin],
    methods: {
    sayHello: function() {
    console.log('Vue instance!')
    }
},
mounted() {
    this.sayHello()
    }
})
​
// Output in console
> Vue instance!
> Vue instance!

我们可以看到,当他们之间没有发生同名冲突的时候,两个都正常打印了。而当他们发生冲突之后。你可以看到这里打印了两个Vue instance。这是因为第一个函数被调用之后,并没有被销毁,而是被重写了。然后被调用了两次

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

选项合并

  • 数据对象(data)在内部会进行递归合并,在和组件的数据发生冲突时以组件数据优先。

  • 同名钩子函数(created,mounted...)将混合为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。

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

需要注意的是

谨慎使用全局混入对象,因为会影响到每个单独创建的 Vue 实例 (包括第三方模板)。大多数情况下,只应当应用于自定义选项。也可以将其用作 Plugins 以避免产生重复应用

所以Vue对mixin 设定了 自定义选项合并策略

自定义选项将使用默认策略,即简单地覆盖已有值。如果想让自定义选项以自定义逻辑合并,可以向 Vue.config.optionMergeStrategies 添加一个函数:

Vue.config.optionMergeStrategies.myOption = function (toVal, fromVal) {
  // 返回合并后的值
}

对于多数值为对象的选项,可以使用与 methods 相同的合并策略:

var strategies = Vue.config.optionMergeStrategies
strategies.myOption = strategies.methods

有时间的,可以看看这篇文件对mixin源码的观察

从源码看 Vue 中的 Mixin

发布了49 篇原创文章 · 获赞 61 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wuyxinu/article/details/103531558