在Vue.js中使用Mixins
前言
今日早讀文章由 @ 池盛星翻譯投稿分享。
正文從這開始~
一個很常見的場景: 你有兩個非常相似的組件, 它們擁有非常相似的基本功能, 但是它們之間又有足夠的不同的地方, 該如何選擇呢? 我們是應該將它們分成兩個完全不同的組件呢? 還是創建一個基礎組件, 然後定義足夠多的props以方便區分使用場景?
這兩種方式都不是完美的: 如果你將它們分成兩個完全不同的組件, 在需求變化(功能變化)時, 可能會增加需要同時修改兩個組件的風險, 這違反了"DRY"的前提. 另一方面, 太多的props很快會讓人變得凌亂, 並且, 迫使維護人員, 甚至是你自己, 要首先理解這些props的上下文才能使用它, 這會讓人非常失望.
Vue的Mixins是非常實用的編程方式, 因為最終實用的編程是通過不斷減少運動部件(moving parts)使代碼變得容易理解. (關於這一點, Michael Feathers有一個很好的引用). 一個mixin允許你封裝一個功能, 以便你能在整個應用程序中的不同組件中使用它. 如果mixin被正確的創建, 它們是純粹的--它們不會修改或更改函數的作用範圍(scope)之外的內容, 因此, 您可以在多個地方執行它們, 並且只要輸入值相同, 總是能非常可靠得得到相同的結果. 這真的非常強大.
基本的例子
假設我們有一些不同的組件, 它們的工作是切換狀態boolean, 一個模態(modal)和一個提示(tooltip). 這些tooltips和modals沒有很多共同之處, 除了這個功能: 它們看起來不一樣, 它們使用起來也不盡相同, 但是它們的邏輯是相似的 .
//modal
constModal={
template: #modal ,
data(){
return{
isShowing:false
}
},
methods:{
toggleShow(){
this.isShowing=!this.isShowing;
}
},
components:{
appChild:Child
}
}
//tooltip
constTooltip={
template: #tooltip ,
data(){
return{
isShowing:false
}
},
methods:{
toggleShow(){
this.isShowing=!this.isShowing;
}
},
components:{
appChild:Child
}
}
我們可以從中提取邏輯, 並創建可以復用的部分:(在CODEPEN中查看效果)
consttoggle={
data(){
return{
isShowing:false
}
},
methods:{
toggleShow(){
this.isShowing=!this.isShowing;
}
}
}
constModal={
template: #modal ,
mixins:[toggle],
components:{
appChild:Child
}
};
constTooltip={
template: #tooltip ,
mixins:[toggle],
components:{
appChild:Child
}
};
這個例子有意保持小而簡單, 是我找到的在實際的應用程序中非常有用的關於mixins的易讀的例子包括但不限於: 獲取viewport和組件的維度, 收集特定的mousemove events, 以及基本的圖表元素. Paul Pflugradt有一個非常不錯的關於Vue Mixins的repo, 值得注意的是, 它們是用coffeescript所寫的.
使用
這個Pen並沒有真正的告訴我們如何在一個真正的應用程序中設置它, 所以, 讓我們來看看:
您可以設置您的目錄結構以任何您喜歡的方式, 但我喜歡創建一個單獨的mixin目錄以方便管理它們. 我們將創建的文件將具有".js"擴展名(而不是.vue, 就像我們其他的文件), 然後我們將導出(export)一個對象為mixin:
然後, 在modal.vue里, 我們可以通過import剛才的toggle來訪問它, 就像這樣:
importChildfrom ./Child
import{toggle}from ./mixins/toggle
exportdefault{
name: modal ,
mixins:[toggle],
components:{
appChild:Child
}
}
很重要的需要意識到的一點是, 儘管如此, 我們使用的是一個對象(object)而不是一個組件(component), 生命周期(lifecycle)內的方法(methods)是可用的. 我們可以掛載(hook)到mounted(), 這樣它就會被應用於組件的生命周期, 使得這種方法非常的靈活和強大.
合并(Merging)
看看最後一個例子, 我們發現, 我們不僅僅擁有我們的功能, 生命周期的鉤子(hooks)也可用於mixin, 所以, 當我們將它應用與具有重疊進程(overlapping processes)的時候, 順序很重要. 默認情況下, mixins將首先被調用, 然後是組件, 所以我們可以根據需要來覆蓋它(override). 就是說, 組件有最後的發言權. 這隻有當衝突發生時才變得非常重要, 在這個時候, 組件必須決定哪一個勝出, 否則一切將被放置在一個數組中執行, mixins相關的放在前面, 然後是組件相關的 .
//mixin
consthi={
mounted(){
console.log( hello from mixin! )
}
}
//vue instance or component
newVue({
el: #app ,
mixins:[hi],
mounted(){
console.log( hello from Vue instance! )
}
});
//Output in console
>hellofrommixin!
>hellofromVue instance!
如果兩個衝突, Vue實例和組件將勝出:
//mixin
consthi={
methods:{
sayHello:function(){
console.log( hello from mixin! )
}
},
mounted(){
this.sayHello()
}
}
//vue instance or component
newVue({
el: #app ,
mixins:[hi],
methods:{
sayHello:function(){
console.log( hello from Vue instance! )
}
},
mounted(){
this.sayHello()
}
})
// Output in console
>hellofromVue instance!
>hellofromVue instance!
您可能已經注意到, 在Vue實例中, 我們有兩個console.log列印而不是一個. 這是因為, mixin解析以後, 在Vue實例中的mounted()裡面會有兩個this.sayHello()調用, 但是由於mixin中的sayHello函數會在Vue實例的sayHello函數之前, 因此被Vue實例中的sayHello函數覆蓋了. 所以, mounted()中調用的兩次sayHello實際上都是Vue實例中的sayHello函數.
全局Mixins
當我們使用術語global參考mixins時, 我們不是指能夠在每個組件訪問它們, 就像過濾器一樣. 我們已經可以在組件中訪問mixins以這種方式: mixins: [toggle].
Global mixins如字面上的意思一樣, 會被應用於所有的組件. 因此, 它們的用例非常有限, 應該慎重考慮. 我可以想到的能夠合理使用的一個場景是像插件一樣的東西, 你可能需要訪問一切. 但是, 即使在這種情況下, 我也會對您正在應用的內容感到擔心, 特別是當您將功能擴展到可能是黑匣子的應用程序時.
要創建全局實例, 我們將其放在Vue實例之前. 在典型的Vue-cli構建中, 這將在您的main.js 文件中 .
Vue.mixin({
mounted(){
console.log( hello from mixin! )
}
})
newVue({
...
})
還是那句話, 謹慎使用這種方式的mixin! 現在, mixin中的console.log將會出現在每一個單獨的組件中. 在這種情況下還不是很糟(除了控制台裡面多了許多噪音外). 但是您會發現, 如果使用不當, 將會帶來多大的危害.
結論
Mixins對於封裝一些可復用的功能非常實用. 它們當然不是您唯一可用的選項: 高階組件(higher order components), 例如, 允許您組合類似的功能, 這只是一種工作方式. 我喜歡mixins, 是因為我們不需要到處傳遞狀態(state), 但是, 這種模式當然也可以被濫用, 所以請仔細考慮哪個選項對您的應用程序是最有意義的 .
關於本文
譯者:@池盛星
作者:@sdrasner
原文:https://css-tricks.com/using-mixins-vue-js
點擊展開全文


※晉陞評審的套路
※螞蟻金服招聘高級前端開發工程師/前端開發專家
※正則表達式回溯法原理
※SVG 新司機開車指南
※webpack正式發布v3.0.0
TAG:前端早讀課 |
※Vue+VueRouter+elememntUI+axios 搭建後台管理系統
※GitHub趨勢:Vue.js大有超過TensorFlow之勢!
※Vue: scoped 樣式與 CSS Module 對比
※教你使用Vue.js的DevTools來調試你的vue項目
※Vue中的methods、watch、computed的區別
※Angular和Vue.js 深度對比
※node+express+mongoDB寫簡單介面,Vue獲取介面
※簡單理解Vue中的nextTick
※Angular、React 當前,Vue.js 優劣幾何?
※Vue.js 為何能逆襲 Angular 和 React 而主導前端?
※Vue-SSR之Nuxt.js 在斗米 B 端實戰
※dotnet core webapi+vue 搭建前後端完全分離web架構(一)
※少女歌劇Revue Starlight-ReLIVE特別舞台
※揚我國威!Bellevue新晉中餐Fine Dining,完全不輸西餐
※揚我國威!Bellevue新晉中餐Fine Dining,完全不輸西餐
※PicGo—基於 electron-vue 的炫酷圖床工具
※.NET Core + Vue.js動態許可權(RBAC)管理系統框架「DncZeus」開源了
※Per.js速度對比Vue.js
※「少女歌劇Revue Starlight-ReLIVE」特別舞台報道
※springboot+vue簡單的後台管理