新聞中心
有一種很常見的情況:有兩個非常相似的組件,他們的基本功能是一樣的,但他們之間又存在著足夠的差異性,此時的你就像是來到了一個分岔路口:我是把它拆分成兩個不同的組件呢?還是保留為一個組件,然后通過props傳值來創(chuàng)造差異性從而進(jìn)行區(qū)分呢?

創(chuàng)新互聯(lián)專注于康馬企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,成都商城網(wǎng)站開發(fā)??雕R網(wǎng)站建設(shè)公司,為康馬等地區(qū)提供建站服務(wù)。全流程按需策劃設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
兩種解決方案都不夠***:如果拆分成兩個組件,你就不得不冒著一旦功能變動就要在兩個文件中更新代碼的風(fēng)險,這違背了 DRY 原則。反之,太多的props傳值會很快變得混亂不堪,從而迫使維護(hù)者(即便這個人是你)在使用組件的時候必須理解一大段的上下文,拖慢寫碼速度。
使用Mixin。Vue 中的Mixin對編寫函數(shù)式風(fēng)格的代碼很有用,因?yàn)楹瘮?shù)式編程就是通過減少移動的部分讓代碼更好理解(引自 Michael Feathers )。Mixin允許你封裝一塊在應(yīng)用的其他組件中都可以使用的函數(shù)。如果使用姿勢得當(dāng),他們不會改變函數(shù)作用域外部的任何東西,因此哪怕執(zhí)行多次,只要是同樣的輸入你總是能得到一樣的值,真的很強(qiáng)大!
基礎(chǔ)實(shí)例
我們有一對不同的組件,它們的作用是通過切換狀態(tài)(Boolean類型)來展示或者隱藏模態(tài)框或提示框。這些提示框和模態(tài)框除了功能相似以外,沒有其他共同點(diǎn):它們看起來不一樣,用法不一樣,但是邏輯一樣。
- // 模態(tài)框
- 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
- }
- }
我們可以在這里提取邏輯并創(chuàng)建可以被重用的項(xiàng):
- const toggle = {
- data() {
- return {
- isShowing: false
- }
- },
- methods: {
- toggleShow() {
- this.isShowing = !this.isShowing;
- }
- }
- }
- const Modal = {
- template: '#modal',
- mixins: [toggle],
- components: {
- appChild: Child
- }
- };
- const Tooltip = {
- template: '#tooltip',
- mixins: [toggle],
- components: {
- appChild: Child
- }
- };
你可以點(diǎn)擊這里,查看 Sarah Drasner(@sdras) 在CodePen上編寫 Mixin 的例子
為了更容易理解Mixin,這個例子故意編寫得簡單一些。真實(shí)應(yīng)用中Mixin有如下的應(yīng)用,但是它的作用也不僅限于此:獲取視窗和組件的尺寸,采集特定的鼠標(biāo)事件和圖表的基本元素。Paul Pflugradt 有一個關(guān)于 Vue Mixins 的優(yōu)秀項(xiàng)目,值得一提的是它是用 coffeescript 編寫的。
用法
上面這個codepen的例子并沒有告訴我們在一個真實(shí)的應(yīng)用中如何使用Mixin,所以我們看看下面的這個。
你可以按照你喜歡的任意方式設(shè)置你的目錄結(jié)構(gòu),但為了結(jié)構(gòu)規(guī)整我喜歡新建一個mixin目錄。我們創(chuàng)建的這個文件含有.js擴(kuò)展名(跟.vue相對,就像我們的其他文件),為了使用Mixin我們需要輸出一個對象。
接著我們可以在Modal.vue使用這樣的寫法,來引入這個Mixin:
- import Child from './Child'
- import { toggle } from './mixins/toggle'
- export default {
- name: 'modal',
- mixins: [toggle],
- components: {
- appChild: Child
- }
- }
即便我們使用的是一個對象而不是一個組件,生命周期函數(shù)對我們來說仍然是可用的,理解這點(diǎn)很重要。我們也可以這里使用mounted()鉤子函數(shù),它將被應(yīng)用于組件的生命周期上。這種工作方式真的很靈活也很強(qiáng)大。
合并
在下面的這個例子,我們可以看到,我們不僅僅是實(shí)現(xiàn)了自己想要的功能,并且Mixin中的生命周期的鉤子也同樣是可用的。因此,當(dāng)我們在組件上應(yīng)用Mixin的時候,有可能組件與Mixin中都定義了相同的生命周期鉤子,這時候鉤子的執(zhí)行順序的問題凸顯了出來。默認(rèn)Mixin上會首先被注冊,組件上的接著注冊,這樣我們就可以在組件中按需要重寫Mixin中的語句。組件擁有最終發(fā)言權(quán)。當(dāng)發(fā)生沖突并且這個組件就不得不“決定”哪個勝出的時候,這一點(diǎn)就顯得特別重要,否則,所有的東西都被放在一個數(shù)組當(dāng)中執(zhí)行,Mixin將要被先推入數(shù)組,其次才是組件。
- //mixin
- const hi = {
- mounted() {
- console.log('hello from mixin!')
- }
- }
- //vue instance or component
- new Vue({
- el: '#app',
- mixins: [hi],
- mounted() {
- console.log('hello from Vue instance!')
- }
- });
- //Output in console
- > hello from mixin!
- > hello from Vue instance!
如果這兩個沖突了,我們看看 Vue實(shí)例或組件是如何決定輸贏的:
- //mixin
- const hi = {
- methods: {
- sayHello: function() {
- console.log('hello from mixin!')
- }
- },
- mounted() {
- this.sayHello()
- }
- }
- //vue instance or component
- new Vue({
- el: '#app',
- mixins: [hi],
- methods: {
- sayHello: function() {
- console.log('hello from Vue instance!')
- }
- },
- mounted() {
- this.sayHello()
- }
- })
- // Output in console
- > hello from Vue instance!
- > hello from Vue instance!
你可能已經(jīng)注意到這有兩個console.log而不是一個——這是因?yàn)?**個函數(shù)被調(diào)用時,沒有被銷毀,它只是被重寫了。我們在這里調(diào)用了兩次sayHello()函數(shù)。
全局Mixin
當(dāng)我們使用“全局”來描述Mixin的時候,我們并不是說Mixin能夠像filter,在每個組件都能被訪問到。只是我們能夠在組件通過mixins:[toggle]訪問組件上的Mixin對象。
全局Mixin被注冊到了每個單一組件上。因此,它們的使用場景極其有限并且在使用的時候我們需要非常小心。一個我能想到的用途就是類似于插件,你需要賦予它訪問所有東西的權(quán)限。但即使在這種情況下,我也對你正在做事情的充滿警惕,尤其當(dāng)你打算為應(yīng)用增加通能的時候,這樣做可能對你來說是個潘多拉的盒子。
為了創(chuàng)建一個全局實(shí)例,我們可以把它放在Vue實(shí)例之上。在一個典型的 Vue-cli 初始化的項(xiàng)目中,它可能在你的main.js文件中。
- Vue.mixin({
- mounted() {
- console.log('hello from mixin!')
- }
- })
- new Vue({
- ...
- })
再次提醒,小心使用它!那個console.log將會出現(xiàn)在每個組件上,在這個案例里還不算壞(除了控制臺上有多余的輸出)。但如果全局Mixin被錯誤的使用,你將能看到它有多可怕。
結(jié)論
Mixin對于封裝一小段想要復(fù)用的代碼來講是有用的。對你來說Mixin當(dāng)然不是唯一可行的選擇:比如說高階組件就允許你組合相似函數(shù),Mixin只是的一種實(shí)現(xiàn)方式。我喜歡Mixin,因?yàn)槲也恍枰獋鬟f狀態(tài),但是這種模式當(dāng)然也可能會被濫用,所以,仔細(xì)思考下哪種選擇對你的應(yīng)用最有意義吧!
網(wǎng)站名稱:在Vue.js中使用Mixin
瀏覽路徑:http://fisionsoft.com.cn/article/djjgcss.html


咨詢
建站咨詢
