zoukankan      html  css  js  c++  java
  • vue数据传递--我有特殊的实现技巧

    前言

    最近碰到了比较多的关于vue的eventBus的问题,之前定技术选型的时候也被问到了,vuex和eventBus的使用范围。所以简单的写一下。同时有一种特殊的实现方案。

    组件之间传值有这么几种数据传递方式,vuex、props、eventBus和特殊的eventBus

    vuex

    我就传两个数据,vuex真是太麻烦了。用是不可能用的,理解又理解不了。

    props

    demo

    父子组件传值,官方api,只写个demo。

    1. 父组件

      
      // 将事件绑定至子组件
      <son :info="info" @update="updateHandler"/>
      // data
      info: 'sendToSon'
      // methods
      updateHandler (newVal) {
        this.info = newVal
      }
      
    2. 子组件

      
      // props
      props: ['info']
      // 触发绑定在组件上的事件,向上传值,在父组件某个方法中使用
      this.$emit('update', 'got')
      

    父向子传值-->props
    子向父传值-->子组件绑定事件回调定义在父组件,子组件触发此事件。
    因不推荐子组件内直接修改父组件传入的props,需使用自定义事件。

    限制

    父子组件。

    eventBus

    demo

    bus皆为导入的bus实例

    
    // bus
    const bus = new Vue()
    // 数据接收组件
    // 当前组件接收值则
    bus.$on('event1', (val)=>{})
    // 数据发出组件
    // 当前组件发出值则
    bus.$emit('event1', val)
    

    可以看出本质是一个vue实例充当事件绑定的媒介。
    在所有实例中使用其进行数据的通信。

    双(多)方使用同名事件进行沟通。

    问题

    1. $emit时,必须已经$on,否则将无法监听到事件,也就是说对组件是有一定的同时存在的要求的。(注:路由切换时,新路由组件先created,旧路由组件再destoryed,部分情况可以分别写入这两个生命周期,见此问题)。
    2. $on在组件销毁后不会自动解除绑定,若同一组件多次生成则会多次绑定事件,则会一次$emit,多次响应,需额外处理。
    3. 数据非“长效”数据,无法保存,只在$emit后生效。

    所以是否有一种更适用的方案呢?

    特殊的eventBus?

    demo

    我们先来看个代码,线上代码
    bus皆为导入的bus实例

    
    // bus
    const bus = new Vue({
      data () {
        return {
          // 定义数据
          val1: ''
        }
      },
      created () {
        // 绑定监听
        this.$on('updateData1', (val)=>{
          this.val1 = val
        })
      }
    })
    

    // 数据发出组件

    
    import bus from 'xx/bus'
    // 触发在bus中已经绑定好的事件
    bus.$emit('update1', '123')
    

    // 数据接收组件

    
    
    {{val1}}
    // 使用computed接收数据
    computed {
      val1 () {
        // 依赖并返回bus中的val1
        return bus.val1
      }
    }
    

    不同

    1. 正统的eventBus只是用来绑定触发事件,并不关心数据,不与数据发生交集。而这个方案多一步将数据直接添加在bus实例上。且事件监听与数据添加需提前定义好。
    2. 数据接收方不再使用$on来得知数据变化,而是通过计算属性的特征被动接收。

    解决的问题

    1. 通信组件需同时存在?数据在bus上存储,所以没有要求。
    2. 多次绑定?绑定监听都在bus上,不会重复绑定。
    3. 数据只在$emit后可用?使用计算属性直接读取存在bus上的值,不需要再次触发事件。

    探讨

    为什么使用计算属性

    其实应该是为什么不能直接添加到data上,如data1: bus.data1?我们可以再看一段代码,线上代码
    将bus修改为

    
    data () {
      return {
        // 多一层结构
        val: {
          result: 0
        }
      }
    },
    created () {
      this.$on('update1', val => {
        console.log('触发1', i1++)
        this.val.result = val
      })
    }
    

    数据接收组件改为

    
    // template
    data中获取直接修改值:{{dataResult}}
    data中获取直接修改值的父层:{{dataVal}}
    computed中依赖直接修改值:{{computedResult}}
    // js
    data () {
        return {
          // 获取直接修改值
          dataResult: bus.val.result,
          // 获取直接修改值的父层
          dataVal: bus.val
        }
      },
      computed: {
        computedResult () {
          // 依赖直接修改值
          return bus.val.result
        }
      }
    

    可以看到,data中获取直接修改值时值的数据是无法动态响应的。

    为什么要用事件

    其实不用$emit触发,使用bus.val = 1直接赋值也是可以的,那么为什么不这么做呢?

    简化版的vuex

    其实这种eventBus就是简化版的vuex。
    vue文档中有这样一段话:

    组件不允许直接修改属于 store 实例的 state,而应执行 action 来分发 (dispatch) 事件通知 store 去改变,我们最终达成了 Flux 架构。这样约定的好处是,我们能够记录所有 store 中发生的 state 改变。

    那么可以用vuex中store对应bus实例,state对应dataaction对应事件dispatch对应$emit
    同时vuex中组件获取数据的方式正是通过计算属性,那么其实vuexFlux架构的理解和使用也没有那么难。

    原文地址:https://segmentfault.com/a/1190000012808179

  • 相关阅读:
    BZOJ3689: 异或之
    BZOJ3166: [Heoi2013]Alo
    BZOJ3261: 最大异或和
    BZOJ3123: [Sdoi2013]森林
    BZOJ4520: [Cqoi2016]K远点对
    BZOJ2989: 数列
    BZOJ1941: [Sdoi2010]Hide and Seek
    BZOJ4066: 简单题
    BZOJ2648: SJY摆棋子
    KDtree模板(HDU4347)
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9959739.html
Copyright © 2011-2022 走看看