本文介紹vue.js組件,具體如下:
5.2 組件通信
盡管子組件可以用this.$parent訪問它的父組件及其父鏈上任意的實例,不過子組件應當避免直接依賴父組件的數據,盡量顯式地使用 props 傳遞數據。另外,在子組件中修改父組件的狀態是非常糟糕的做法,因為:
1.這讓父組件與子組件緊密地耦合;
2.只看父組件,很難理解父組件的狀態。因為它可能被任意子組件修改!理想情況下,只有組件自己能修改它的狀態。
每個Vue實例都是一個事件觸發器:
5.2.1 監聽與觸發
v-on監聽自定義事件:
<!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 。例如:
<my-component v-on:click.native="doTheThing"></my-component>
5.2.2 派發事件——$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>
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>
和派發事件相反。前者在子組件綁定,調用$dispatch派發到父組件;後者在父組件中綁定,調用$broadcast廣播到子組件。
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) { // ... })
在更多復雜的情況下,可以考慮使用專門的 狀態管理模式。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。