前提: vue 组件懒加载 ()=>import() 这种方式引入组件
首次加载不触发, A 组件 emit,B 组件 on, 当 A 组件触发事件加载 B 组件时, 因为 B 组件还未加载, 自然 this.$root.bus.$emit 监听不到 B 中的事件, 也就触发不了.(如果不采用组件懒加载则没问题)
多次监听事件, 因每次进入 B 组件都会 on 一次事件, 这会类似于元素 addEventListner 一样, 建立多次监听, 故触发事件时会多次触发事件.
- /* 需要每次销毁组件时取消监听 */
- beforeDestroy: function () {
- this.$root.Bus.$offV(['emitName1', 'emitName2'...])
- }
A 中 emit,B 和 C 中有相同名字的 on, 如'init', 当触发 A 时, 组件由 B 改为 C, 此时触发的不是 C 中的 init, 而是 B 中的.
如果非懒加载引入, 则会两个 init 都触发.
个人解决方案:
弃用 Bus, 当只是一个简单的传值或者不涉及到首次要触发事件时才使用. 虽说不采用组件懒加载使用是没问题, 但为了程序的优化, 还是推荐组件懒加载.
A 中改变数据, 关联 Vuex 中数据, 组件 B,C 中 watch Vuex 中数据有无改变, 从而触发相应事件.
watch 这种方式, 首次是不触发的. B,C 如要实现首次即可触发, 在 watch 中加参数 immdiate: true 即可.
当然还有蠢一点的方法, 即 mounted 中主动触发一次事件.
- // 例 :
- watch:{
- serachValue:{
- handler:"methodName" // 方法名
- immediate:true // 默认是 false
- }
- }
- // 当然也可以这么写
- watch: {
- serachValue: {
- immediate: true,
- handler (newValue,oldValue) { // 直接写方法
- this.methodName()
- }
- }
- }
watch 这种方式如若 newValue 和 oldValue 相同, 则不会触发 handler. 如若要实现不改变值也要触发事件怎么办.
- /* Vuex 中 部分代码 */
- state: {
- isCheck: 0,
- watchIsCheck: 0, // 监测 isCheck 是否有被重新赋值, 不管 newValue 是否等于 oldValue,isCheck 改变时, 设值为时间戳用于保持唯一性, 用于在组件中监听, 从而实现不管之前是否是相同的, 一样触发相应事件
- },
- mutations: {
- changeIsCheck (state, val) {
- state.watchIsCheck = new Date().getTime()
- state.isCheck = val
- }
- }
- /* 组件中 */
- import {mapStates} from Vuex
- // 此处忽略将 mapstates 注册的代码
- watch:{
- watchIsCheck(){
- // 此时 this.isCheck 已经最新改变过的了, 不管是否前后一样.
- this.doSomething()
- }
- }
总结: 总的来说, bus 这个东西用来用去感觉不怎么好用. 相较于 Vuex, 灵活性差很多. 父子组件传值有自己的方式也用不到它. 遇坑时问了一个 vue 的大牛, 推荐我学 provide 和 inject, 错略看了下, 比较高级的用法, 还没有时间去学.
来源: http://www.jianshu.com/p/d0e3c479224b