Vue — 詳解mixins混入使用,應(yīng)用場(chǎng)景

混入是vue官方文檔提出的 關(guān)于vue復(fù)用性的一種方式,看了文檔似懂,查找了下網(wǎng)上的講解,整理下好好縷一縷這個(gè)東西

前言

當(dāng)我們的項(xiàng)目越來越大,我們會(huì)發(fā)現(xiàn)組件之間可能存在很多相似的功能,你在一遍又一遍的復(fù)制粘貼相同的代碼段(data,method,watch、mounted等),如果我們?cè)诿總€(gè)組件中去重復(fù)定義這些屬性和方法會(huì)使得項(xiàng)目出現(xiàn)代碼冗余并提高了維護(hù)難度,針對(duì)這種情況官方提供了Mixins特性

一、什么是Mixins? mixins是一個(gè)js對(duì)象

混入 (mixin) 提供了一種非常靈活的方式,來分發(fā) Vue 組件中的可復(fù)用功能。一個(gè)混入對(duì)象可以包含任意組件選項(xiàng)。當(dāng)組件使用混入對(duì)象時(shí),所有混入對(duì)象的選項(xiàng)將被“混合”進(jìn)入該組件本身的選項(xiàng)。

mixins(混入),官方的描述是一種分發(fā) Vue 組件中可復(fù)用功能的非常靈活的方式,mixins是一個(gè)js對(duì)象,它可以包含我們組件中script項(xiàng)中的任意功能選項(xiàng),如data、components、methods 、created、computed等等。

我們只要將共用的功能以對(duì)象的方式傳入 mixins選項(xiàng)中,當(dāng)組件引用 mixins對(duì)象時(shí)所有mixins對(duì)象的選項(xiàng)都將被混入該組件本身的選項(xiàng)中來,這樣就可以提高代碼的重用性,使你的代碼保持干凈和易于維護(hù)。

image.png

放大看這張圖:右邊就是一個(gè)混入對(duì)象; 左邊引用了混入對(duì)象

二、什么時(shí)候使用Mixins?

當(dāng)我們存在多個(gè)組件中的數(shù)據(jù)或者功能很相近時(shí),我們就可以利用mixins將公共部分提取出來,通過 mixins封裝的函數(shù),組件調(diào)用他們是不會(huì)改變函數(shù)作用域外部的。
作用: 減少data、methods、鉤子的重復(fù)
????????
文章最后會(huì)舉例應(yīng)用場(chǎng)景~

三、如何創(chuàng)建Mixins?

在src目錄下創(chuàng)建一個(gè)mixins文件夾,文件夾下新建一個(gè)myMixins.js文件。前面我們說了mixins是一個(gè)js對(duì)象,所以應(yīng)該以對(duì)象的形式來定義myMixins,在對(duì)象中我們可以和vue組件一樣來定義我們的data、components、methods 、created、computed等屬性,并通過export導(dǎo)出該對(duì)象


image.png

四、如何使用Mixins?

前面在myMixins.js中輸出一個(gè)混入對(duì)象,然后在需要調(diào)用的組件中引入myMixins.js文件即可


image.png

五、Mixins的特點(diǎn)

特點(diǎn)1:方法和參數(shù)在各組件中不共享,雖然組件調(diào)用了mixins并將其屬性合并到自身組件中來了,但是其屬性只會(huì)被當(dāng)前組件所識(shí)別并不會(huì)被共享。

??也就是當(dāng)前組件對(duì)mixins的屬性的修改,其他也引用了這個(gè)mixins的組件并不會(huì)受影響。??

① 首先我們?cè)诨旌蠈?duì)象myMixins.js中定義一個(gè)age字段和getAge方法

export const myMixins = {
  components:{},
  data() {
    return {
      age: 18,
    }
  },
  mounted() {
    this.getAge()
  },
  methods: {
    getAge() {
      console.log(this.age)
    }
  }
}

② 此時(shí)組件1引用了這個(gè)mixins,組件1中對(duì)num進(jìn)行+1操作

// 這是組件1
import { myMixins } from "@/mixins/myMixins.js";
export default {
  mixins: [myMixins],
  data() {
    return {}
  },
  created() {
    this.age++   // 組件1的age變成了19啦
  },
}

③ 組件2不進(jìn)行操作

export default {
  mixins: [myMixins],
  data() {
    return {}
  },
}

④ 我們分別切換到兩個(gè)頁面,查看控制臺(tái)輸出。會(huì)發(fā)現(xiàn)組件1改變了age里面的值,組件2中age值還是混合對(duì)象的初始值,并沒有隨著組件1的增加而改變


image.png

特點(diǎn)2:引入mixins后,組件會(huì)對(duì)其進(jìn)行合并,將mixins中的數(shù)據(jù)和方法拓展到當(dāng)前組件中來,如果當(dāng)前組件也有同名稱的屬性或者方法,在合并的過程中會(huì)出現(xiàn)沖突,接下來我們?cè)敿?xì)了解Mixins合并沖突

六、Mixins合并沖突

【6.1】混入對(duì)象里的(components、methods 、computed、data)這些選項(xiàng),混入組件時(shí)選項(xiàng)會(huì)被合并,重名沖突時(shí)優(yōu)先采用組件的 ??,組件中的鍵會(huì)覆蓋混入對(duì)象的

① 我們?cè)诨烊雽?duì)象增加age屬性、getAge1方法和getAge2方法

// myMixins.js
export const myMixins = {
  components:{},
  data() {
    return {
      age: 18,
    }
  },
  methods: {
    getAge1() {
      console.log("age1 from mixins =", this.age )
    },
    getAge2() {
      console.log("age2 from mixins =", this.age )
    },
  }
}

② 我們?cè)谝肓薽yMixins文件的組件中,增加age屬性、getAge1方法和getAge3方法

// template.vue
import { myMixins } from "@/mixins/myMixins.js";
export default {
  mixins: [myMixins],
  data() {
    return {
      age: 20,
    }
  },
  mounted() {
    this.getAge1();
    this.getAge2();
    this.getAge3();
  },
  methods: {
    getAge1() {
      console.log('age1 from template =', this.age)
    },
    getAge3() {
      console.log('age3 from template =', this.age)
    },
  }
}

③ 我們會(huì)發(fā)現(xiàn):
組件中的age覆蓋了混合對(duì)象的age,
組件的getAge1方法覆蓋了混合對(duì)象的getAge1方法


image.png

【6.2】值為函數(shù)(created、mounted)的選項(xiàng),混入組件時(shí)選項(xiàng)會(huì)被合并調(diào)用,
?? 混合對(duì)象里的鉤子函數(shù)在組件里的鉤子函數(shù)之前調(diào)用

// myMixins.js
export const myMixins = {
  components:{},
  data() {
    return {}
  },
  created() {
    console.log('xxx from mixins')
  }
}

再看看引用了mixins的組件

import { myMixins } from "@/mixins/myMixins.js";
export default {
  mixins: [myMixins],
  data() {
    return {}
  },
  created() {
    console.log('xxx from template')
  }
}

結(jié)果 mixins自己的created 比 引用了mixins的組件里的created先執(zhí)行


image.png

七、全局混入

嚴(yán)重警告:一旦使用全局混入,它將影響每一個(gè)之后創(chuàng)建的 Vue 實(shí)例。
使用恰當(dāng)時(shí),這可以用來為自定義選項(xiàng)注入處理邏輯。

// 為自定義的選項(xiàng) 'myOption' 注入一個(gè)處理器。
Vue.mixin({
  created: function () {
    var myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

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

不建議使用全局混入,全局注冊(cè)之后會(huì)對(duì)所有組件都生效,影響比較大,項(xiàng)目大的情況下,建議使用局部注冊(cè)

八、同時(shí)引入多個(gè)mixin對(duì)象

同時(shí)引入多個(gè) mixins: [mixinsTest2,mixinsTest]

在使用局部注冊(cè)的時(shí)候,可同時(shí)引入多個(gè)混入對(duì)象,執(zhí)行順序和引入順序一致,此處便不再贅述了。

結(jié)論: 引入多個(gè)以后,,我們先引入的先被使用,先引用,先使用!

九、與vuex的區(qū)別

vuex:用來做狀態(tài)管理的,里面定義的變量在每個(gè)組件中均可以使用和修改,在任一組件中修改此變量的值之后,其他組件中此變量的值也會(huì)隨之修改。

Mixins:可以定義共用的變量,在每個(gè)組件中使用,引入組件中之后,各個(gè)變量是相互獨(dú)立的,值的修改在組件中不會(huì)相互影響。

十、與公共組件的區(qū)別

組件:在父組件中引入組件,相當(dāng)于在父組件中給出一片獨(dú)立的空間供子組件使用,然后根據(jù)props來傳值,但本質(zhì)上兩者是相對(duì)獨(dú)立的。

Mixins:則是在引入Mixins之后,Mixins與組件中的屬性和方法進(jìn)行合并,相當(dāng)于擴(kuò)展了父組件的對(duì)象與方法,可以理解為形成了一個(gè)新的組件。

????

另外,vue不建議,子組件直接修改props接收到的父組件的數(shù)據(jù),但是,混入可以做到組件的屬性或者方法覆蓋混入對(duì)象的


混入的應(yīng)用場(chǎng)景

假設(shè)我們需要在每個(gè)組件上添加name和time。在created、destroyed時(shí),打出提示,并給出存活時(shí)間。

一共有五個(gè)組件,請(qǐng)問怎么做?
做法1:給每個(gè)組件添加data和created, destroyed鉤子,重復(fù)5次
做法2:使用mixin減少重復(fù)。

做法1:

<template>
    <div>child1</div>
</template>
<script>
    export default{
        data(){
            return {
                name:'child1',
                time_birth:undefined,
                time_dead:undefined
            }
        },
        created(){
            this.time_birth=new Date();
            console.log(this.name+'出生了');
        },
        beforeDestroy(){
            this.time_dead=new Date();
            console.log(`${this.name}死了,共存活了${this.time_dead-this.time_birth}ms`);
        }
    }
</script>

// 依次對(duì)組件2 3 4 5 分別執(zhí)行這些操作。。。

做法1小結(jié): 代碼重復(fù)太多,基本上每個(gè)組件都在復(fù)刻第一個(gè)組件的樣式,這樣下來,代碼的維護(hù)性是十分低的。萬一有一天要改需求了怎么辦?又倒回去重新修改5次嗎?5次并不是真正的5次,萬一是10次,100次呢?很顯然,這種做法并不可取。接下來來看另外一種做法。

做法2:
創(chuàng)建混入對(duì)象:

const myMixin = {
    data(){
            return {
                /* 每個(gè)組件的名字不同,用另外的方法賦值。即每個(gè)組件自己帶上自己的名字即可。 */
                name:undefined,
                time_birth:undefined,
                time_dead:undefined
            }
        },
        created(){
            if(!this.name){
                throw new Error('need name');  // 名字是用的組件里data的name
            }
            this.time_birth=new Date();
            console.log(this.name+'出生了');
        },
        beforeDestroy(){
            this.time_dead=new Date();
            console.log(`${this.name}死了,共存活了${this.time_dead-this.time_birth}ms`);
        }
}
export default myMixin;

組件里

<template>
    <div>child1</div>
</template>
<script>
    /* 首先導(dǎo)入公共部分的js內(nèi)容 */
    import myMixin from './Mixins/public.js';
    export default{
        data(){
            return {
                /* 其他組件就寫自己組件的名字即可 */
                name:'child1',
            }
        },
        /* 使用導(dǎo)入的public模塊 */
        mixins:[myMixin],
    }
</script>

用了混入后,組件只需要引用混入對(duì)象,然后在data里填寫組件的名字,再掛載一下混入對(duì)象,就好了。

今天就聊到這里,后續(xù)有想到栗子再補(bǔ)充吧 ??
??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容