Vue组件间通信

2,265 阅读2分钟

一边学习前端,一边通过博客的形式自己总结一些东西,当然也希望帮助一些和我一样开始学前端的小伙伴。

如果出现错误,请在评论中指出,我也好自己纠正自己的错误

author: thomaszhou

vue组件间通信

  • 父子组件之间-数据通信
  • 父子组件之间-方法通信
  • 兄弟组件之间-通信

写Vue项目的过程中,组件之间的通信非常频繁,像父子通信的props和$emit方法是很多人都知道的,当然我这里肯定也要提一提嘛~但是兄弟间的通信方法大部分都是提倡构建evenBus

父子组件之间-数据通信

父组件向子组件传递(props)

  • 父组件引用子组件的时候利用v-bind去绑定mseeage,传递给子组件(对应就是msg)
  • 子组件要创建props选项,注册传递的msg值,就可以直接使用msg这个值了

父组件

<template>
    <child :msg="message"></child>
</template>

<script>
import child from './child.vue';
export default {
    components: {
        child
    },
    data () {
        return {
            message: 'father message';
        }
    }
}
</script>

子组件vue

<template>
    <div>{{msg}}</div>
</template>

<script>
export default {
    props: {
        msg: {
            type: String,
            required: true
        }
    }
}
</script>

父组件直接获取子组件的数据(this.$refs.ref的名字.变量

// 假设我们要获取子组件<son></son>的数据target
// 第一:子组件son要设置ref
<son ref="sonComponent"></son>
// 第二:用下面的语句去获取,修改子组件的值
console.log(this.$refs.sonComponent.target); // 取值
this.$refs.sonComponent.target = '1'; // 修改值

子组件向父组件传递数据(emit)+ 子组件调用父组件方法

子组件通过 $emit 触发父组件的方法(通过@add-parent-total="addTotal将 add-parent-total 和 addTotal联系起来)

  • 子组件通过$emit触发add-parent-total事件
  • 父组件在引入组件时设置,@add-parent-total="addTotal",其中addTotal是父组件的方法
//html
<child @add-parent-total="addTotal"></child>
//根组件
var vm = new Vue({
    el: "#app",
    data:{
        total: 0
    },
    components: {
        Child
    },
    methods: {
//根组件中子组件改变根组件的方法
        addTotal(args){
            this.total++
            console.log(args);//args就是传递值带的的参数
        }
    }
})
//定义子组件
var Child = {
//获取data()中的数据,并添加一个点击事件
    template: `<button @click="addCounter">{{counter}}</button>`,
    data(){
        return {
            counter: 0
        }
    },
    methods:{
        addCounter(){
            this.counter++;
            //自定义事件$emit传回根组件,同时调用根组件方法
            this.$emit('add-parent-total',args)
        }
    }
}

父子组件之间-方法通信

  • 父组件 --> 子组件:

    • ==引用子组件 并起名ref="demo1"然后 通过 this.$refs.demo1.getUser(elem) 调用子组件中的getUser方法并传参(elem)==
  • 子组件 --> 父组件:

    • 方法一:子组件直接用this.$parent.xxxx这样直接调用父组件的方法。
    • 方法二: 引用子组件并用 v-on 来做个监测的函数来检测;子组件通过this.$emit('方法名',传递的参数)来调用父组件的方法
  • 父组件代码

// 调用子组件
<son-demo ref="demo1" @sonname="son1"></son-demo>  <!--一些要写明的属性-->
import sonDemo from '../components/sondemo.vue'
export default {
    data() {
      return {
        sondemoVal: 'test'
      };
    },
    mounted() {
      this.$refs.demo1.getUser(this.sondemoVal); // 父 --> 子的方法
    },
    methods: {
      son1(temp) {
        console.log(`这里是父组件的方法son1:${temp}`);
	  }
    },
}
  • 子组件
<template>
    <div>{{msg}}</div>
</template>
export default {
    methods: {
      getUser(temp) {
        console.log('sondemo--->'+temp);
	  }
	},
	mounted() {
          // this.$parent.son1('son'); 子 --> 父的方法一:
         this.$emit('sonname','son'); // 子 --> 父的方法二:
         // 'son'是传递的参数
	}
}

兄弟组件之间-通信(或者非兄弟,非父子组件)

  • 适用于兄弟组件的情况 和 非父子,非兄弟组件的情况

    • 方法一(使用简单的情况):自己创建一个事件总线eventBus来作为通信的桥梁(也适用于非父子,非兄弟组件的情况)
    • 方法二(程序比较复杂的情况)那就用Vuex(也适用于非父子,非兄弟组件的情况)
    • 方法三⚠️:如果仅仅是某一个页面,或者很少的页面有兄弟组件A,B(非兄弟组件不适用)通信的问题,推荐:**将该部分逻辑写在父组件内,通过this.emit()发送到父组件进行逻辑的编写,然后通过this.refs.子组件name(要自己提前设置),来取到另一个子组件的值,具体如下

    举例: 子组件A 要修改 子组件B 的time值???
    
    <son1 refs="son1" @changeElem = "change"></son1>
    <son2 refs="son2"></son2>
    
    思路:
        子组件son1:click触发一个$emit("changeElem", val);要将son2组件的time修改为val
        父组件: 通过@changeElem = "change"接收事件,编写change方法
        change(elem) {
            this.$refs.son2.time = elem;
        }
    

Vuex的用法看这里

这里主要讲方法一

vue2中废弃了dispatch和broadcast广播和分发事件的方法。

所以在vue2.0中可以通过实例一个vue实例Bus作为媒介,要相互通信的兄弟组件之中,都引入Bus,之后通过分别调用Bus事件触发和监听来实现组件之间的通信和参数传递

  • 创建一个eventBus.js作为桥梁(例子直接把js文件放在与组件同一个目录下),内容如下:
import Vue from 'vue'
export default new Vue;
  • 创建两个子组件,son1.vue 和 son2.vue
// son1.vue 发送值

<template>
	<div class="ex">
		<button @click="sendMsg">点击我传送值</button>
	</div>
</template>

<script>
  import Bus from './eventBus' // 引入eventBus文件
  export default {
    data () {
      return {
	  }
    },
	methods: {
      sendMsg() {
        Bus.$emit('msg', '我要传给兄弟组件们,你收到没有');//传递msg,第二个参数就是msg的值
	  }
	}
  }
</script>
// son2.vue 接受值

<template>
	<div class="ex">
		{{message}}
	</div>
</template>

<script>
  import Bus from './eventBus' // 引入eventBus文件
  export default {
    data () {
      return {
        message: '变化前'
	  }
    },
	mounted() {
        let self = this;
        // 利用$on来监听msg值
        Bus.$on('msg', (e) => {
            self.message = e;
            console.log(`传来的数据是:${e}`);
        });
	}
  }
</script>