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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。