vue数据传递--我有特殊的实现技巧

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

有这么几种数据传递方式,vuex、props、eventBus和特殊的eventBus。vue

vuex

不介绍,数据量和复杂度达不到不用它你才会向下看。java

props

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

1.父组件api

<son :info="info" @update="updateHandler"/>

// data
info: 'sendToSon'

// methods
updateHandler (newVal) {
 this.info = newVal
}

  

2.子组件架构

// props
props: ['info']

// 向上传值,某个方法中使用
this.$emit('update', 'got')

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

 

eventBus

bus皆为导入的bus实例spa

// bus
const bus = new Vue()

// 数据接收组件

// 当前组件接收值则

bus.$on('event1', (val)=>{})

// 数据发出组件

// 当前组件发出值则

bus.$emit('event1', val)

能够看出本质是一个vue实例充当事件绑定的媒介。 在全部实例中使用其进行数据的通讯。code

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

问题

  1. $emit时,必须已经 $on,不然将没法监听到事件,也就是说对组件是有必定的同时存在的要求的。(注:路由切换时,新路由组件先 created,旧路由组件再destoryed,部分状况能够分别写入这两个生命周期,见此问题)。

  2. $on在组件销毁后不会自动解除绑定,若同一组件屡次生成则会屡次绑定事件,则会一次 $emit,屡次响应,需额外处理。

  3. 数据非“长效”数据,没法保存,只在 $emit后生效。

 

因此是否有一种更适用的方案呢?

特殊的eventBus?

咱们先来看个代码,线上代码。 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 改变。

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

相关文章
相关标签/搜索