天天看點

聊聊Vue.js元件間通信的幾種姿勢

寫在前面

因為對Vue.js很感興趣,而且平時工作的技術棧也是Vue.js,這幾個月花了些時間研究學習了一下Vue.js源碼,并做了總結與輸出。

文章的原位址:https://github.com/answershuto/learnVue。

在學習過程中,為Vue加上了中文的注釋https://github.com/answershuto/learnVue/tree/master/vue-src,希望可以對其他想學習Vue源碼的小夥伴有所幫助。

可能會有了解存在偏差的地方,歡迎提issue指出,共同學習,共同進步。

什麼是Vue元件?

元件 (Component) 是 Vue.js 最強大的功能之一。元件可以擴充 HTML 元素,封裝可重用的代碼。在較高層面上,元件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,元件也可以是原生 HTML 元素的形式,以 is 特性擴充。

Vue元件間通信

父元件向子元件通信

方法一:props

使用props,父元件可以使用props向子元件傳遞資料。

父元件vue模闆father.vue

<template>
    <child :msg="message"></child>
</template>

<script>

import child from './child.vue';

export default {
    components: {
        child
    },
    data () {
        return {
            message: 'father message';
        }
    }
}
</script>
           

子元件vue模闆child.vue

<template>
    <div>{{msg}}</div>
</template>

<script>
export default {
    props: {
        msg: {
            type: String,
            required: true
        }
    }
}
</script>
           

方法二 使用$children

使用$children可以在父元件中通路子元件。

子元件向父元件通信

方法一:使用vue事件

父元件向子元件傳遞事件方法,子元件通過$emit觸發事件,回調給父元件。

父元件vue模闆father.vue

<template>
    <child @msgFunc="func"></child>
</template>

<script>

import child from './child.vue';

export default {
    components: {
        child
    },
    methods: {
        func (msg) {
            console.log(msg);
        }
    }
}
</script>
           

子元件vue模闆child.vue

<template>
    <button @click="handleClick">點我</button>
</template>

<script>
export default {
    props: {
        msg: {
            type: String,
            required: true
        }
    },
    methods () {
        handleClick () {
            //........
            this.$emit('msgFunc');
        }
    }
}
</script>
           

方法二: 通過修改父元件傳遞的props來修改父元件資料

這種方法隻能在父元件傳遞一個引用變量時可以使用,字面變量無法達到相應效果。因為飲用變量最終無論是父元件中的資料還是子元件得到的props中的資料都是指向同一塊記憶體位址,是以修改了子元件中props的資料即修改了父元件的資料。

但是并不推薦這麼做,并不建議直接修改props的值,如果資料是用于顯示修改的,在實際開發中我經常會将其放入data中,在需要回傳給父元件的時候再用事件回傳資料。這樣做保持了元件獨立以及解耦,不會因為使用同一份資料而導緻資料流異常混亂,隻通過特定的接口傳遞資料來達到修改資料的目的,而内部資料狀态由專門的data負責管理。

方法三:使用$parent

使用$parent可以通路父元件的資料。

非父子元件、兄弟元件之間的資料傳遞

非父子元件通信,Vue官方推薦使用一個Vue執行個體作為中央事件總線。

Vue内部有一個事件機制,可以參考源碼。

$on方法用來監聽一個事件。

$emit用來觸發一個事件。

/*建立一個Vue執行個體作為中央事件總嫌*/
let event = new Vue();

/*監聽事件*/
event.$on('eventName', (val) => {
    //......do something
});

/*觸發事件*/
event.$emit('eventName', 'this is a message.');
           

多層級父子元件通信:

在Vue1.0中實作了 broadcast與 dispatch兩個方法用來向子元件(或父元件)廣播(或派發),當子元件(或父元件)上監聽了事件并傳回true的時候會向爺孫級元件繼續廣播(或派發)事件。但是這個方法在Vue2.0裡面已經被移除了。

之前在學習餓了麼的開源元件庫element的時候發現他們重新實作了broadcast以及dispatch的方法,以mixin的方式引入,具體可以參考《說說element元件庫broadcast與dispatch》。但是跟Vue1.0的兩個方法實作有略微的不同。這兩個方法實作了向子孫元件事件廣播以及向多層級父元件事件派發的功能。但是并非廣義上的事件廣播,它需要指定一個commentName進行向指定元件名元件定向廣播(派發)事件。

其實這兩個方法内部實作還是用到的還是 parent以及 children,用以周遊子節點或是逐級向上查詢父節點,通路到指定元件名的時候,調用$emit觸發指定事件。

複雜的單頁應用資料管理

當應用足夠複雜情況下,請使用vuex進行資料管理。

關于

作者:染陌

Email:[email protected] or [email protected]

Github: https://github.com/answershuto

Blog:http://answershuto.github.io/

知乎首頁:https://www.zhihu.com/people/cao-yang-49/activities

知乎專欄:https://zhuanlan.zhihu.com/ranmo

掘金: https://juejin.im/user/58f87ae844d9040069ca7507

osChina:https://my.oschina.net/u/3161824/blog

轉載請注明出處,謝謝。

歡迎關注我的公衆号

聊聊Vue.js元件間通信的幾種姿勢

繼續閱讀