5.2 組件通訊javascript
儘管子組件能夠用this.$parent訪問它的父組件及其父鏈上任意的實例,不過子組件應當避免直接依賴父組件的數據,儘可能顯式地使用 props 傳遞數據。另外,在子組件中修改父組件的狀態是很是糟糕的作法,由於: html
每一個Vue實例都是一個事件觸發器:vue
5.2.1 監聽與觸發java
v-on監聽自定義事件:json
<!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> // 註冊子組件 // 將當前消息派發出去 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 = ''; } } } }) // 初始化父組件 // 在收到消息時將事件推入一個數組中 var parent = new Vue({ el: '#events-example', data: { messages: [] }, methods:{ 'handleIt': function(){ alert("a"); } } }) </script> </html>
父組件能夠在使用子組件的地方直接用 v-on 來監聽子組件觸發的事件:數組
<!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>
在某個組件的根元素上監聽一個原生事件。能夠使用 .native 修飾v-on 。例如:app
<my-component v-on:click.native="doTheThing"></my-component>
5.2.2 派發事件——$dispatch()ide
<!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>
5.2.3 廣播事件——$broadcast()ui
<!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>
和派發事件相反。前者在子組件綁定,調用$dispatch派發到父組件;後者在父組件中綁定,調用$broadcast廣播到子組件。this
5.2.4 父子組件之間的訪問
$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">顯示子組件的數據</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">顯示子組件的數據</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">顯示父組件的數據</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>
如開篇所提,不建議在子組件中修改父組件的狀態。
5.2.5 非父子組件通訊
有時候非父子關係的組件也須要通訊。在簡單的場景下,使用一個空的 Vue 實例做爲中央事件總線:
var bus = new Vue()
// 觸發組件 A 中的事件 bus.$emit('id-selected', 1)
// 在組件 B 建立的鉤子中監聽事件 bus.$on('id-selected', function (id) { // ... })
在更多複雜的狀況下,能夠考慮使用專門的 狀態管理模式。
參考:http://www.cnblogs.com/keepfool/p/5637834.html
《vue.js權威指南》