vue.js入門(3)——詳解組件通信
本文介紹vue.js組件,具體如下:
5.2 組件通信
盡管子組件可以用this.$parent訪問它的父組件及其父鏈上任意的實例,不過子組件應(yīng)當避免直接依賴父組件的數(shù)據(jù),盡量顯式地使用 props 傳遞數(shù)據(jù)。另外,在子組件中修改父組件的狀態(tài)是非常糟糕的做法,因為:
1.這讓父組件與子組件緊密地耦合;
2.只看父組件,很難理解父組件的狀態(tài)。因為它可能被任意子組件修改!理想情況下,只有組件自己能修改它的狀態(tài)。
每個Vue實例都是一個事件觸發(fā)器:
- $on()——監(jiān)聽事件。
- $emit()——把事件沿著作用域鏈向上派送。(觸發(fā)事件)
- $dispatch()——派發(fā)事件,事件沿著父鏈冒泡。
- $broadcast()——廣播事件,事件向下傳導(dǎo)給所有的后代。
5.2.1 監(jiān)聽與觸發(fā)
v-on監(jiān)聽自定義事件:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <!--子組件模板--> <template id="child-template"> <input v-model="msg" /> <button v-on:click="notify">Dispatch Event</button> </template> <!--父組件模板--> <div id="events-example"> <p>Messages: {{ messages | json }}</p> <child v-on:child-msg="handleIt"></child> </div> </body> <script src="js/vue.js"></script> <script> // 注冊子組件 // 將當前消息派發(fā)出去 Vue.component('child', { template: '#child-template', data: function (){ return { msg: 'hello' } }, methods: { notify: function() { if(this.msg.trim()){ this.$dispatch('child-msg',this.msg); this.msg = ''; } } } }) // 初始化父組件 // 在收到消息時將事件推入一個數(shù)組中 var parent = new Vue({ el: '#events-example', data: { messages: [] }, methods:{ 'handleIt': function(){ alert("a"); } } }) </script> </html>
父組件可以在使用子組件的地方直接用 v-on 來監(jiān)聽子組件觸發(fā)的事件:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="counter-event-example"> <p>{{ total }}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter> </div> </body> <script src="js/vue.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> Vue.component('button-counter', { template: '<button v-on:click="increment">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { increment: function () { this.counter += 1 this.$emit('increment') } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script> </html>
在某個組件的根元素上監(jiān)聽一個原生事件。可以使用 .native 修飾v-on 。例如:
<my-component v-on:click.native="doTheThing"></my-component>
5.2.2 派發(fā)事件——$dispatch()
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <p>Messages: {{ messages | json }}</p> <child-component></child-component> </div> <template id="child-component"> <input v-model="msg" /> <button v-on:click="notify">Dispatch Event</button> </template> <script src="js/vue.js"></script> <script> // 注冊子組件 Vue.component('child-component', { template: '#child-component', data: function() { return { msg: '' } }, methods: { notify: function() { if (this.msg.trim()) { this.$dispatch('child-msg', this.msg) this.msg = '' } } } }) // 初始化父組件 new Vue({ el: '#app', data: { messages: [] }, events: { 'child-msg': function(msg) { this.messages.push(msg) } } }) </script> </body> </html>
- 子組件的button元素綁定了click事件,該事件指向notify方法
- 子組件的notify方法在處理時,調(diào)用了$dispatch,將事件派發(fā)到父組件的child-msg事件,并給該該事件提供了一個msg參數(shù)
- 父組件的events選項中定義了child-msg事件,父組件接收到子組件的派發(fā)后,調(diào)用child-msg事件。
5.2.3 廣播事件——$broadcast()
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <input v-model="msg" /> <button v-on:click="notify">Broadcast Event</button> <child-component></child-component> </div> <template id="child-component"> <ul> <li v-for="item in messages"> 父組件錄入了信息:{{ item }} </li> </ul> </template> <script src="js/vue.js"></script> <script> // 注冊子組件 Vue.component('child-component', { template: '#child-component', data: function() { return { messages: [] } }, events: { 'parent-msg': function(msg) { this.messages.push(msg) } } }) // 初始化父組件 new Vue({ el: '#app', data: { msg: '' }, methods: { notify: function() { if (this.msg.trim()) { this.$broadcast('parent-msg', this.msg) } } } }) </script> </body> </html>
和派發(fā)事件相反。前者在子組件綁定,調(diào)用$dispatch派發(fā)到父組件;后者在父組件中綁定,調(diào)用$broadcast廣播到子組件。
5.2.4 父子組件之間的訪問
- 父組件訪問子組件:使用$children或$refs
- 子組件訪問父組件:使用$parent
- 子組件訪問根組件:使用$root
$children:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <parent-component></parent-component> </div> <template id="parent-component"> <child-component1></child-component1> <child-component2></child-component2> <button v-on:click="showChildComponentData">顯示子組件的數(shù)據(jù)</button> </template> <template id="child-component1"> <h2>This is child component 1</h2> </template> <template id="child-component2"> <h2>This is child component 2</h2> </template> <script src="js/vue.js"></script> <script> Vue.component('parent-component', { template: '#parent-component', components: { 'child-component1': { template: '#child-component1', data: function() { return { msg: 'child component 111111' } } }, 'child-component2': { template: '#child-component2', data: function() { return { msg: 'child component 222222' } } } }, methods: { showChildComponentData: function() { for (var i = 0; i < this.$children.length; i++) { alert(this.$children[i].msg) } } } }) new Vue({ el: '#app' }) </script> </body> </html>
$ref可以給子組件指定索引ID:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <parent-component></parent-component> </div> <template id="parent-component"> <!--<child-component1></child-component1> <child-component2></child-component2>--> <child-component1 v-ref:cc1></child-component1> <child-component2 v-ref:cc2></child-component2> <button v-on:click="showChildComponentData">顯示子組件的數(shù)據(jù)</button> </template> <template id="child-component1"> <h2>This is child component 1</h2> </template> <template id="child-component2"> <h2>This is child component 2</h2> </template> <script src="js/vue.js"></script> <script> Vue.component('parent-component', { template: '#parent-component', components: { 'child-component1': { template: '#child-component1', data: function() { return { msg: 'child component 111111' } } }, 'child-component2': { template: '#child-component2', data: function() { return { msg: 'child component 222222' } } } }, methods: { showChildComponentData: function() { // for (var i = 0; i < this.$children.length; i++) { // alert(this.$children[i].msg) // } alert(this.$refs.cc1.msg); alert(this.$refs.cc2.msg); } } }) new Vue({ el: '#app' }) </script> </body> </html>
效果與$children相同。
$parent:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> <parent-component></parent-component> </div> <template id="parent-component"> <child-component></child-component> </template> <template id="child-component"> <h2>This is a child component</h2> <button v-on:click="showParentComponentData">顯示父組件的數(shù)據(jù)</button> </template> <script src="js/vue.js"></script> <script> Vue.component('parent-component', { template: '#parent-component', components: { 'child-component': { template: '#child-component', methods: { showParentComponentData: function() { alert(this.$parent.msg) } } } }, data: function() { return { msg: 'parent component message' } } }) new Vue({ el: '#app' }) </script> </body> </html>
如開篇所提,不建議在子組件中修改父組件的狀態(tài)。
5.2.5 非父子組件通信
有時候非父子關(guān)系的組件也需要通信。在簡單的場景下,使用一個空的 Vue 實例作為中央事件總線:
var bus = new Vue() // 觸發(fā)組件 A 中的事件 bus.$emit('id-selected', 1) // 在組件 B 創(chuàng)建的鉤子中監(jiān)聽事件 bus.$on('id-selected', function (id) { // ... })
在更多復(fù)雜的情況下,可以考慮使用專門的 狀態(tài)管理模式。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解決Vue使用bus總線時,第一次路由跳轉(zhuǎn)時數(shù)據(jù)沒成功傳遞問題
這篇文章主要介紹了解決Vue使用bus總線時,第一次路由跳轉(zhuǎn)時數(shù)據(jù)沒成功傳遞問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07Vue中通過屬性綁定為元素綁定style行內(nèi)樣式的實例代碼
這篇文章主要介紹了Vue中通過屬性綁定為元素綁定style行內(nèi)樣式,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04Vue Element UI 表單自定義校驗規(guī)則及使用
這篇文章主要介紹了Vue Element UI 表單自定義效驗規(guī)則及使用,文中通過代碼介紹了常見表單效驗規(guī)則,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02如何巧用Vue.extend繼承組件實現(xiàn)el-table雙擊可編輯(不使用v-if、v-else)
這篇文章主要給大家介紹了關(guān)于如何巧用Vue.extend繼承組件實現(xiàn)el-table雙擊可編輯的相關(guān)資料,不使用v-if、v-else,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-06-06VUE搭建分布式醫(yī)療掛號系統(tǒng)的前臺預(yù)約掛號步驟詳情
這篇文章主要介紹了VUE搭建分布式醫(yī)療掛號系統(tǒng)的前臺預(yù)約掛號步驟詳情,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04