$on绑定事件内部的组件实例
具体现象:
在全局事件总线中使用$on触发的事件,在方法内部调用this中的data时发现,data中的值全部为初始值。无法获取到已经修改过的data中的数据。
组件1:
<template>
<div>
<input type="text" placeholder="请输入姓名" v-model="formData.name">
<input type="text" placeholder="请输入年龄" v-model="formData.age">
<button @click="submit">提交</button>
</div>
</template>
<script>
import EventBus from "../demo";
export default {
name: 'Component1',
data() {
return {
formData:{
name: '',
age: '',
}
};
},
created() {
// 清除上次的,防止被多次调用
EventBus.$off('log');
EventBus.$on('log',this.test);
},
methods: {
submit(){
this.$emit('submit');
},
test(){
console.log(this.formData)
// 输出结果是{name:'',age:''}
}
},
}
</script>
<style></style>
组件2:
<template>
<div></div>
</template>
<script>
import EventBus from "../demo";
export default {
name: 'Component2',
data() {
return {
};
},
created() {
// 清除上次的,防止被多次调用
EventBus.$off('submit');
EventBus.$on('submit',this.emit);
},
methods: {
emit(){
EventBus.$emit('log')
}
},
}
</script>
<style></style>
在组件1的输入框中都输入内容
然后点击提交按钮
最终调用test() 方法,发现最终打印出来的formData的值全部都是空的,此时去查看Vue dev tools发现,组件上的formData是有值的。
问题原因:
官方的原因未找到,个人推测是因为EventBus的$on触发的方法,内部的this指向的是在created生命周期时的组件实例,在那个时候,组件的所有data都是初始化的状态,因此打印出来的formData为空,Devtool中看到的是当前的组件实例。
解决方案:
- 使用vuex或者依赖注入替代。
- 传递this
组件1:
<template>
<div>
<input type="text" placeholder="请输入姓名" v-model="formData.name">
<input type="text" placeholder="请输入年龄" v-model="formData.age">
<button @click="submit">提交</button>
</div>
</template>
<script>
import EventBus from "../demo";
export default {
name: 'Component1',
data() {
return {
formData:{
name: '',
age: '',
}
};
},
created() {
// 清除上次的,防止被多次调用
EventBus.$off('log');
EventBus.$on('log',this.test);
},
methods: {
submit(){
// 把当前最新的组件实例传递给组件2
this.$emit('submit',this);
},
// 接受到的最新的组件实例
test(that){
console.log(that.formData)
}
},
}
</script>
<style></style>
组件2:
<template>
<div></div>
</template>
<script>
import EventBus from "../demo";
export default {
name: 'Component2',
data() {
return {
};
},
created() {
// 清除上次的,防止被多次调用
EventBus.$off('submit');
EventBus.$on('submit',this.emit);
},
methods: {
// 接受组件1给的this,并将这个this再次传回给组件1
emit(that){
EventBus.$emit('log',that)
}
},
}
</script>
<style></style>
如上述代码所示,在组件1中将当前最新的组件实例传递给组件2,由组件2传回给组件1,在组件1触发的方法中使用最新的组件实例上的方法和数据,此时打印出来的结果就变成了最新输入的数据。组件1对应方法中需要用到this的地方需要全部替换为that