阅读 74

关于Vue eventBus总线传值时的生命周期问题

在Vue的非父子组件传递数据时,我们会用到Vue的bus总线机制,也就是在Vue的原型上声明一个vue实例,通过Vue的属性来链接各个页面。

Vue.prototype.$eventBus = new Vue()

有的时候我们需要从B页面返回A页面时带回数据来赋值给A页面,比如:在B页面点击返回方法中触发$emit(),然后在A页面的mounted()中监听$on()并赋值给A页面的某个变量,但是我们发现并没有效果,无法正确赋值。

如下代码所示:当你在A页面中点击跳转到B页面以后,再点击B页面回到A页面时,想通过$emit()$on()方法赋值,但是发现并不能达到预期效果。

  • A页面
<template>
  <div>
    <button @click="handleTap">点击跳转B页面</button>
    <div>msg:{{msg}}</div>
  </div>
</template>

<script>
export default {
  data(){
    return {
      msg: "msg"
    }
  },
  mounted(){
    this.$eventBus.$on("handle",(res)=>{
      this.msg = res;
    })
  }
}
复制代码
  • B页面
handletap(){
  this.$eventBus.$emit("handle","成功");
  this.$router.go(-1);
}
复制代码

Vue的bus总线机制总的来说主要有几个关键点:

1.需要先监听$on()、后触发$emit()

2.注意$on()触发的生命周期问题:

  a.如果是两个组件都已经加载完了比如父与子组件,$on()可以放在mounted()生命周期中;

  b.如果两个组件是有顺序的加载,比如页面A到页面B,$on()需要放在created()生命周期中;

  这里我们主要讨论b情况,如果我们按以下写法

  • A页面
mounted(){
  this.$eventBus.$off();
  this.$eventBus.$on("handle",(res)=>{
    this.msg = res;
    console.log(this.msg, "A mounted-监听handle")
  })
  console.log("A mounted")
}
复制代码
  • B页面
methods:{
  handleTap() {
    this.$eventBus.$emit("handle", "成功");
    console.log("触发handle");
    this.$router.go(-1);
  }
}
复制代码

我们无法成功将msg赋值,打印的生命周期如下图:

  在监听成功时A页面压根就还没开始加载,连beforeCreate()都没开始,所以这个时候监听事件触发以后并不能成功赋值:

  要保证监听事件在触发事件之前,还要保证触发的时候生命周期无误,由上面失败的案例中打印的生命周期可知,B页面的触发事件只能写在beforeDestroy()或者destroyed()之中,而A页面的监听事件只能放在beforeCreate()created()beforeMount()之中。

  • A页面
created(){
  this.$eventBus.$off();
  this.$eventBus.$on("handle",(res)=>{
    this.msg = res;
    console.log(this.msg, "A created-监听handle")
  })
  console.log("A created")
}
复制代码
  • B页面
beforeDestroy(){
  this.$eventBus.$emit("handle", "成功");
  console.log("触发handle")
  console.log("B beforeDestroy")
}
复制代码

  监听事件正确的出现在了相应的生命周期之后这样是可以成功触发传值的。打印的生命周期如下图: