您好,登錄后才能下訂單哦!
vue組件通信分為橫向和縱向。
**縱向**
1. props 和 $emit
props:接收來自父組件的數據
$emit:觸發事件
<!DOCTYPE?html> <html?lang="en"> <head> <meta?charset="UTF-8"> <meta?name="viewport"?content="width=device-width,?initial-scale=1.0"> <meta?http-equiv="X-UA-Compatible"?content="ie=edge"> <title>Document</title> </head> <body> <div?id="app"> </div> <script?src="./node_modules/vue/dist/vue.js"></script> <script> //?全局組件 Vue.component('Parent',?{ data(){ return?{ msg:?'I?am?the?data?of?Parent!', childToParentData:?'I?am?the?data?of?Parent!', }; }, template:?`<div> ????????????????????<p>?I?am?the?parent?component!</p> ????????????????????<Child?:childData="msg"?@childHandler="handerFn"/> ????????????????????<p>childToParentData:?{{childToParentData}}</p> ????????????????</div>`, methods:?{ handerFn(val){ console.log(val); this.childToParentData?=?val; }, } }) Vue.component('Child',?{ data(){ return?{ msg:?'I?am?the?data?of?Child!', inputVal:?this.childData, }; }, props:?['childData'], template:?`<div> ????????????????????<p>?I?am?the?child?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<input?v-model="inputVal"?@input="changeVal(inputVal)"?/> ????????????????</div>`, methods:?{ changeVal(val){ //?通過?$emit?觸發,參數為?事件名,參數 this.$emit('childHandler',?val); } } }) var?App?=?{ template:?`<div> ????????????????????<Parent?/> ????????????????</div>`, }; var?vm?=?new?Vue({ el:?'#app', data(){ return?{ }; }, components:?{ App }, methods:?{ }, template:?` ????????????<App?/> ????????????` }) </script> <pre> 子組件向父組件傳值 1、自定義事件 2、子組件原生事件 3、原生事件的處理函數中通過$emit觸發自定義事件 注:子組件不能修改props中的值,否則報錯,可通過子組件自己的數據接收props中的值來解決 </pre> </body> </html>
2. $parent 和 $children
后代組件可以通過$parent.$parent.$parent這種形式跨級通信
父組件可以通過$children[0].$children[0]這種形式跨級通信,如果有多個子組件,索引不好控制
<!DOCTYPE?html> <html?lang="en"> <head> <meta?charset="UTF-8"> <meta?name="viewport"?content="width=device-width,?initial-scale=1.0"> <meta?http-equiv="X-UA-Compatible"?content="ie=edge"> <title>Document</title> </head> <body> <div?id="app"> </div> <script?src="./node_modules/vue/dist/vue.js"></script> <script> //?全局組件 Vue.component('Parent',?{ data(){ return?{ msg:?'I?am?the?data?of?Parent!', grandToParent:?'', }; }, template:?`<div> ????????????????????<p>?I?am?the?parent?component!</p> ????????????????????<input?v-model="msg"?@input="consoleFn"/>? ????????????????????<p?>{{grandToParent}}</p>????????????????????? ????????????????????<hr?/> ????????????????????<Child/> ????????????????</div>`, methods:?{ consoleFn(){ this.$children[0].parentMsg?=?this.msg; }, }, }) Vue.component('Child',?{ data(){ return?{ msg:?'I?am?the?data?of?Child!', parentMsg:?'', grandToChild:?'', }; }, template:?`<div> ????????????????????<p>?I?am?the?child?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<button?@click="consoleFn">attr</button>? ????????????????????<p?>{{parentMsg}}</p>??????????????????? ????????????????????<p?>{{grandToChild}}</p>??????????????????? ????????????????????<hr?/> ????????????????????<GrandChild?/> ????????????????</div>`, methods:?{ consoleFn(){ this.$children[0].childMsg?=?this.msg; }, }, }) Vue.component('GrandChild',?{ data(){ return?{ msg:?'I?am?the?data?of?GrandChild!', childMsg:?'', }; }, template:?`<div> ????????????????????<p>?I?am?the?GrandChild?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<button?@click="consoleFn"?>attr</button> ????????????????????<p?>{{childMsg}}</p>? ????????????????????<hr?/> ????????????????</div>`, methods:?{ consoleFn(){ this.$parent.grandToChild?=?this.msg; this.$parent.$parent.grandToParent?=?this.msg; }, }, }) var?App?=?{ template:?`<div> ????????????????????<Parent?/> ????????????????</div>`, }; var?vm?=?new?Vue({ el:?'#app', data(){ return?{ }; }, components:?{ App }, methods:?{ }, template:?` ????????????<App?/> ????????????` }) </script> <pre> $parent,?$children,?$root,?$parent.$parent 非響應式,如果有多個直接子組件 </pre> </body> </html>
3. $attrs 和 $listeners
后代組件從$attrs獲取父組件傳給后代組件的數據
后代組件通過$emit觸發$listeners的事件將數據傳給父組件
<!DOCTYPE?html> <html?lang="en"> <head> <meta?charset="UTF-8"> <meta?name="viewport"?content="width=device-width,?initial-scale=1.0"> <meta?http-equiv="X-UA-Compatible"?content="ie=edge"> <title>Document</title> </head> <body> <div?id="app"> </div> <script?src="./node_modules/vue/dist/vue.js"></script> <script> //?全局組件 Vue.component('Parent',?{ data(){ return?{ msg:?'I?am?the?data?of?Parent!', childToParentData:?'I?am?the?data?of?Parent!', }; }, template:?`<div> ????????????????????<p>?I?am?the?parent?component!</p> ????????????????????<p>childToParentData:?{{childToParentData}}</p> ????????????????????<button?@click="consoleFn">attr</button> ????????????????????<br?/> ????????????????????<Child?:parentMsg="msg"?@childClick="parentHandler"?v-bind="$attrs"?v-on="$listeners"/> ????????????????</div>`, //?inheritAttr:?false, methods:?{ consoleFn(){ console.log(this.$attrs);??//?{} console.log(this.$listeners);??//?{} }, parentHandler(data){ console.log(data); }, }, }) Vue.component('Child',?{ data(){ return?{ msg:?'I?am?the?data?of?Child!', }; }, template:?`<div> ????????????????????<p>?I?am?the?child?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<button?@click="consoleFn">attr</button>???????????????????? ????????????????????<br?/> ????????????????????<GrandChild?:childMsg="msg"?@grandChildClick="childHandler"?v-bind="$attrs"?v-on="$listeners"/> ????????????????</div>`, //?inheritAttr:?false, methods:?{ consoleFn(){ console.log(this.$attrs);??//?{parentMsg:?} console.log(this.$listeners);??//{childClick:?} }, childHandler(data){ console.log(data); }, }, }) Vue.component('GrandChild',?{ data(){ return?{ msg:?'I?am?the?data?of?GrandChild!', }; }, template:?`<div> ????????????????????<p>?I?am?the?GrandChild?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<button?@click="consoleFn"?>attr</button> ????????????????????<br?/> ????????????????</div>`, //?inheritAttr:?false, methods:?{ consoleFn(){ console.log(this.$attrs);??//?{parentMsg:?,?childMsg:?} console.log(this.$listeners);???//{childClick:?,?grandChildClick:?} this.$emit('childClick',?this.msg);??//?如果不收集,$emit只能觸發其父級的事件 this.$emit('grandChildClick',?this.msg);? }, }, }) var?App?=?{ template:?`<div> ????????????????????<Parent?/> ????????????????</div>`, }; var?vm?=?new?Vue({ el:?'#app', data(){ return?{ }; }, components:?{ App }, methods:?{ }, template:?` ????????????<App?/> ????????????` }) </script> <pre> 1、$attrs收集屬性 2、$listeners收集事件 </pre> </body> </html>
4. provide 和 inject
父組件向后代組件單向傳遞數據
<!DOCTYPE?html> <html?lang="en"> <head> <meta?charset="UTF-8"> <meta?name="viewport"?content="width=device-width,?initial-scale=1.0"> <meta?http-equiv="X-UA-Compatible"?content="ie=edge"> <title>Document</title> </head> <body> <div?id="app"> </div> <script?src="./node_modules/vue/dist/vue.js"></script> <script> //?全局組件 Vue.component('Parent',?{ data(){ return?{ msg:?'I?am?the?data?of?Parent!', }; }, provide(){ return?{ parentMsg:?this.msg, }; }, template:?`<div> ????????????????????<p>?I?am?the?parent?component!</p> ????????????????????<input?v-model="msg"/>??<!--?provide和inject綁定并不是可響應的,?所以msg的變化不會影響后代組件中已經接收到的msg的值?--> ????????????????????<button?@click="consoleFn">attr</button> ????????????????????<hr?/> ????????????????????<Child/> ????????????????</div>`, methods:?{ consoleFn(){ console.log(this); }, }, }) Vue.component('Child',?{ data(){ return?{ msg:?'I?am?the?data?of?Child!', }; }, provide:?{ childMsg:?'I?am?the?data?of?Child!', }, inject:?['parentMsg'], template:?`<div> ????????????????????<p>?I?am?the?child?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<button?@click="consoleFn">attr</button>? ????????????????????<p?>{{parentMsg}}</p>??????????????????? ????????????????????<hr?/> ????????????????????<GrandChild?/> ????????????????</div>`, methods:?{ consoleFn(){ console.log(this); }, }, }) Vue.component('GrandChild',?{ data(){ return?{ msg:?'I?am?the?data?of?GrandChild!', }; }, inject:?['parentMsg',?'childMsg'], template:?`<div> ????????????????????<p>?I?am?the?GrandChild?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<button?@click="consoleFn"?>attr</button> ????????????????????<p?>{{parentMsg}}</p>? ????????????????????<p?>{{childMsg}}</p>? ????????????????????<hr?/> ????????????????</div>`, methods:?{ consoleFn(){ console.log(this); }, }, }) var?App?=?{ template:?`<div> ????????????????????<Parent?/> ????????????????</div>`, }; var?vm?=?new?Vue({ el:?'#app', data(){ return?{ }; }, components:?{ App }, methods:?{ }, template:?` ????????????<App?/> ????????????` }) </script> <pre> 單向 </pre> </body> </html>
**橫向**
1. 數據總線?
用一個中間變量保存數據
var bus = new Vue()?
? ?$on綁定事件
? ?$emit觸發事件
<!DOCTYPE?html> <html?lang="en"> <head> <meta?charset="UTF-8"> <meta?name="viewport"?content="width=device-width,?initial-scale=1.0"> <meta?http-equiv="X-UA-Compatible"?content="ie=edge"> <title>Document</title> </head> <body> <div?id="app"> </div> <script?src="./node_modules/vue/dist/vue.js"></script> <script> var?bus?=?new?Vue(); //?全局組件 Vue.component('Parent',?{ data(){ return?{ msg:?'I?am?the?data?of?Parent!', }; }, template:?`<div> ????????????????????<p>?I?am?the?parent?component!</p> ????????????????????<button?@click="consoleFn">button</button> ????????????????????<br?/> ????????????????????<BrotherOne?/> ????????????????????<BrotherTwo?/> ????????????????</div>`, methods:?{ consoleFn(){ console.log(bus); }, }, }) Vue.component('BrotherOne',?{ data(){ return?{ msg:?'I?am?the?data?of?BrotherOne!', fromBrother:?'', }; }, template:?`<div> ????????????????????<p>?I?am?the?BrotherOne?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<input?v-model="fromBrother"?@input="transformData"/>??????????????????? ????????????????????<br?/> ????????????????</div>`, methods:?{ transformData(){ bus.$emit('globalBus',?this.fromBrother); }, }, }) Vue.component('BrotherTwo',?{ data(){ return?{ msg:?'I?am?the?data?of?BrotherTwo!', fromBrother:?'', }; }, template:?`<div> ????????????????????<p>?I?am?the?BrotherTwo?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<p>fromBrother:?{{fromBrother}}</p> ????????????????????<button?@click="consoleFn"?>button</button> ????????????????????<br?/> ????????????????</div>`, methods:?{ consoleFn(){ console.log(bus); }, }, mounted(){ bus.$on('globalBus',?val?=>?{ this.fromBrother?=?val; }) } }) var?App?=?{ template:?`<div> ????????????????????<Parent?/> ????????????????</div>`, }; var?vm?=?new?Vue({ el:?'#app', data(){ return?{ }; }, components:?{ App }, methods:?{ }, template:?` ????????????<App?/> ????????????` }) </script> </body> </html>
var bus = {}
<!DOCTYPE?html> <html?lang="en"> <head> <meta?charset="UTF-8"> <meta?name="viewport"?content="width=device-width,?initial-scale=1.0"> <meta?http-equiv="X-UA-Compatible"?content="ie=edge"> <title>Document</title> </head> <body> <div?id="app"> </div> <script?src="./node_modules/vue/dist/vue.js"></script> <script> var?bus?=?{}; //?全局組件 Vue.component('Parent',?{ data(){ return?{ msg:?'I?am?the?data?of?Parent!', }; }, template:?`<div> ????????????????????<p>?I?am?the?parent?component!</p> ????????????????????<button?@click="consoleFn">button</button> ????????????????????<br?/> ????????????????????<BrotherOne?/> ????????????????????<BrotherTwo?/> ????????????????</div>`, methods:?{ consoleFn(){ console.log(bus); }, }, }) Vue.component('BrotherOne',?{ data(){ return?{ msg:?'I?am?the?data?of?BrotherOne!', fromBrother:?'', }; }, template:?`<div> ????????????????????<p>?I?am?the?BrotherOne?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<input?v-model="fromBrother"?@input="transformData"/>??????????????????? ????????????????????<br?/> ????????????????</div>`, methods:?{ transformData(){ bus['brotherOne']?=?{ 'fromBrother':?this.fromBrother, }; }, }, }) Vue.component('BrotherTwo',?{ data(){ return?{ msg:?'I?am?the?data?of?BrotherTwo!', fromBrother:?'', }; }, template:?`<div> ????????????????????<p>?I?am?the?BrotherTwo?component!</p> ????????????????????<p>{{msg}}</p> ????????????????????<p>fromBrother:?{{fromBrother}}</p> ????????????????????<button?@click="consoleFn"?>button</button> ????????????????????<br?/> ????????????????</div>`, methods:?{ consoleFn(){ this.fromBrother?=?bus['brotherOne']['fromBrother']; }, }, }) var?App?=?{ template:?`<div> ????????????????????<Parent?/> ????????????????</div>`, }; var?vm?=?new?Vue({ el:?'#app', data(){ return?{ }; }, components:?{ App }, methods:?{ }, template:?` ????????????<App?/> ????????????` }) </script> </body> </html>
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。