关键词搜索

全站搜索
×
密码登录在这里
×
注册会员
×

已有账号? 请点击

忘记密码

已有账号? 请点击

使用其他方式登录

vue bus页面传参触发2次问题和数据无法更新问题

发布2022-03-05 浏览822次

详情内容

在vue项目中,各组件之间是需要传值的,有时候非父子关系的组件也需要通信。在简单的场景下,使用一个空的Vue实例作为中央事件总线。称为中央事件总线传值。

通过建立中间的事件bus总线。实现非父子组件之间的数据通信。

首先建立事件bus,我会新建一个bus.js文件;注册bus。
分别在组件中使用emit和on实现数据之间的通信;

bus.js

```

        //bus.js,注册Bus
        import Vue from 'vue'
        export default new Vue()
```

在A页面emit,触发事件,在B页面会执行多次,vue bus页面传参触发2次问题和数据无法更新问题,

A页面:

bus.$emit('selectedAccount', {account_id:this.account_id, account_name: this.account_name});


B页面:

bus.$on('selectedAccount',(data)=>{})

image.png



页面A发送方(组件emit触发事件)

```


        <template>
                 <div class="add-task" :class="{'ishide':isAdding}"  @click="addtask()">
                <i class="fa fa-plus-circle" aria-hidden="true"></i>
                添加任务
                </div>
        </template>
        <script>
        import Bus from '@/bus'
        export default {
        methods: {
        props: ['index'],
        data () {
                return {
                        isAdding: false
                }
        },
        addtask () {
        this.isAdding = true
        Bus.$emit('adding-task', this.isAdding, this.index)  // 这里触发的事件是'adding-task',
        传递了两个参数,分别是this.isAdding和this.index
        this.$emit('addtask')
                        }
                }
        }

```

页面B接收方(on接收事件)

```

        // 模板中的代码就不展示了。
        主要展示的是script中的代码
        export default{
        data() //  这里的数据也不一一显示啦;
        created () {
        // 这里使用on监听了adding-task事件,接收到两个参数。所以一旦上面的组件中的adding-task事件触发,这里就会监听到。
        Bus.$on('adding-task', (state, index) => {
                if (this.index === index) {
                this.isShow = state
                }
                })
                }
        }
```

中央事件总线的坑

当完成上述中央事件总线传值之后,就可以在接收方接收到正常的值,但是会存在一些问题:

就是我第一次进去list页面的时候,我随便点击一下list下的任何一个item,控制台没有输出。但是当我第二次再点击触发事件的时候,就会输出一个测试数据。再一次进去点击,就输出两个数据。。。依次增加了。(控制台上那个“这是从上个页面传来的数据”就是测试数据)

所以,有两个问题。

问题:

  • 问题1: 为什么第一次触发的时候页面B中的on事件没有被触发

  • 问题2: 为什么后面再一次依次去触发的时候会出现,每一次都会发现好像之前的on事件分发都没有被撤销一样,导致每一次的事件触发执行越来越多。

问题一

第一次触发的时候页面B中的on事件没有被触发

产生原因

当我们还在页面A的时候,页面B还没生成,也就是页面B中的 created中所监听的来自于A中的事件还没有被触发。这个时候当你A中emit事件的时候,B其实是没有监听到的。

解决办法

我们可以把A页面组件中的emit事件写在beforeDestory中去。因为这个时候,B页面组件已经被created了,也就是我们写的on事件已经触发了,所以可以在beforeDestory的时候,on事件已经触发了,所以可以在beforeDestory的时候,emit事件

```

        // 修改一下A页面中的代码:
        // 这是原先的代码
        editList (index, date, item) {
        //  点击进入编辑的页面,需要传递的参数比较多。
                console.log(index, date, item)
                this.item = item.type
                this.date = date
                this.$router.replace({path: '/moneyRecord'})
                }
        // 重新在data属性内部定义新的变量,来存储要传过去的数据;
        然后:
        beforeDestroy () {
        console.log(this.highlight, '这是今年的数据', this, '看看组件销毁之前会发生什么')
        bus.$emit('get', {
                item: this.item,
                date: this.date
                })
        },
```

问题二

后面再一次依次去触发的时候会出现,每一次都会发现好像之前的on事件分发都没有被撤销一样,导致每一次的事件触发执行越来越多。

产生原因

就是说,这个$on事件是不会自动清楚销毁的,需要我们手动来销毁。(不过我不太清楚这里的external bus 是什么意思,有大神能解答一下的吗,尤大大也提到如果是注册的是external bus 的时候需要清除)

解决办法

在B组件页面中添加Bus.$off来关闭

######示例代码

```

        // 在B组件页面中添加以下语句,在组件beforeDestory的时候销毁。
        beforeDestroy () {
                bus.$off('get', this.myhandle)
        },

```

总结

所以,如果想要用bus 来进行页面组件之间的数据传递,需要注意亮点,组件Aemit事件应在beforeDestory生命周期内。其次,组件B内的emit事件应在beforeDestory生命周期内。其次,组件B内的on记得要销毁


点击QQ咨询
开通会员
返回顶部
×
  • 微信支付
微信扫码支付
微信扫码支付
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
确定支付下载