天天看點

在Vue.js中使用Mixin

有一種很常見的情況:有兩個非常相似的元件,他們的基本功能是一樣的,但他們之間又存在着足夠的差異性,此時的你就像是來到了一個分岔路口:我是把它拆分成兩個不同的元件呢?還是保留為一個元件,然後通過props傳值來創造差異性進而進行區分呢?

兩種解決方案都不夠完美:如果拆分成兩個元件,你就不得不冒着一旦功能變動就要在兩個檔案中更新代碼的風險,這違背了 dry

原則。反之,太多的props傳值會很快變得混亂不堪,進而迫使維護者(即便這個人是你)在使用元件的時候必須了解一大段的上下文,拖慢寫碼速度。

使用mixin。vue 中的mixin對編寫函數式風格的代碼很有用,因為函數式程式設計就是通過減少移動的部分讓代碼更好了解(引自

michael feathers

)。mixin允許你封裝一塊在應用的其他元件中都可以使用的函數。如果使用姿勢得當,他們不會改變函數作用域外部的任何東西,是以哪怕執行多次,隻要是同樣的輸入你總是能得到一樣的值,真的很強大!

基礎執行個體

我們有一對不同的元件,它們的作用是通過切換狀态(boolean類型)來展示或者隐藏模态框或提示框。這些提示框和模态框除了功能相似以外,沒有其他共同點:它們看起來不一樣,用法不一樣,但是邏輯一樣。

// 模态框 

const modal = { 

  template: '#modal', 

  data() { 

    return { 

      isshowing: false 

    } 

  }, 

  methods: { 

    toggleshow() { 

      this.isshowing = !this.isshowing; 

  components: { 

    appchild: child 

  } 

// 提示框 

const tooltip = { 

  template: '#tooltip', 

}  

我們可以在這裡提取邏輯并建立可以被重用的項:

const toggle = { 

  mixins: [toggle], 

}; 

};  

你可以點選這裡,檢視 sarah drasner(@sdras) 在codepen上編寫 mixin 的例子

為了更容易了解mixin,這個例子故意編寫得簡單一些。真實應用中mixin有如下的應用,但是它的作用也不僅限于此:擷取視窗群組件的尺寸,采集特定的滑鼠事件和圖表的基本元素。paul

pflugradt 有一個關于 vue mixins 的優秀項目,值得一提的是它是用 coffeescript 編寫的。

用法

上面這個codepen的例子并沒有告訴我們在一個真實的應用中如何使用mixin,是以我們看看下面的這個。

你可以按照你喜歡的任意方式設定你的目錄結構,但為了結構規整我喜歡建立一個mixin目錄。我們建立的這個檔案含有.js擴充名(跟.vue相對,就像我們的其他檔案),為了使用mixin我們需要輸出一個對象。

在Vue.js中使用Mixin

接着我們可以在modal.vue使用這樣的寫法,來引入這個mixin:

import child from './child' 

import { toggle } from './mixins/toggle' 

export default { 

  name: 'modal', 

即便我們使用的是一個對象而不是一個元件,生命周期函數對我們來說仍然是可用的,了解這點很重要。我們也可以這裡使用mounted()鈎子函數,它将被應用于元件的生命周期上。這種工作方式真的很靈活也很強大。

合并

在下面的這個例子,我們可以看到,我們不僅僅是實作了自己想要的功能,并且mixin中的生命周期的鈎子也同樣是可用的。是以,當我們在元件上應用mixin的時候,有可能元件與mixin中都定義了相同的生命周期鈎子,這時候鈎子的執行順序的問題凸顯了出來。預設mixin上會首先被注冊,元件上的接着注冊,這樣我們就可以在元件中按需要重寫mixin中的語句。元件擁有最終發言權。當發生沖突并且這個元件就不得不“決定”哪個勝出的時候,這一點就顯得特别重要,否則,所有的東西都被放在一個數組當中執行,mixin将要被先推入數組,其次才是元件。

//mixin 

const hi = { 

  mounted() { 

    console.log('hello from mixin!') 

//vue instance or component 

new vue({ 

  el: '#app', 

  mixins: [hi], 

    console.log('hello from vue instance!') 

}); 

//output in console 

> hello from mixin! 

> hello from vue instance!  

如果這兩個沖突了,我們看看 vue執行個體或元件是如何決定輸赢的:

    sayhello: function() { 

      console.log('hello from mixin!') 

    this.sayhello() 

      console.log('hello from vue instance!') 

}) 

// output in console 

> hello from vue instance! 

你可能已經注意到這有兩個console.log而不是一個——這是因為第一個函數被調用時,沒有被銷毀,它隻是被重寫了。我們在這裡調用了兩次sayhello()函數。

全局mixin

當我們使用“全局”來描述mixin的時候,我們并不是說mixin能夠像filter,在每個元件都能被通路到。隻是我們能夠在元件通過mixins:[toggle]通路元件上的mixin對象。

全局mixin被注冊到了每個單一元件上。是以,它們的使用場景極其有限并且在使用的時候我們需要非常小心。一個我能想到的用途就是類似于插件,你需要賦予它通路所有東西的權限。但即使在這種情況下,我也對你正在做事情的充滿警惕,尤其當你打算為應用增加通能的時候,這樣做可能對你來說是個潘多拉的盒子。

為了建立一個全局執行個體,我們可以把它放在vue執行個體之上。在一個典型的 vue-cli 初始化的項目中,它可能在你的main.js檔案中。

vue.mixin({ 

  ... 

})  

再次提醒,小心使用它!那個console.log将會出現在每個元件上,在這個案例裡還不算壞(除了控制台上有多餘的輸出)。但如果全局mixin被錯誤的使用,你将能看到它有多可怕。

結論

mixin對于封裝一小段想要複用的代碼來講是有用的。對你來說mixin當然不是唯一可行的選擇:比如說高階元件就允許你組合相似函數,mixin隻是的一種實作方式。我喜歡mixin,因為我不需要傳遞狀态,但是這種模式當然也可能會被濫用,是以,仔細思考下哪種選擇對你的應用最有意義吧!

作者:佚名

來源:51cto

繼續閱讀