vue组件通信
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>
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。