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

转载
vue数据传递–我有特殊的实现技巧

项目背景:
pc管理后台,自己封装了一个弹窗组件,是个空的盒子,用意是在每次需要的时候,直接调用此组件,形成弹窗。
后面有个需求,需要在弹窗中实现一个form表单的填写与校验,需求不复杂,但是代码数量较大,所以选择单独做一个组件,形成了嵌套组件。
现在需要在组件间传值
类似:

import
import
父组件
子组件
通用的弹窗组件
在弹窗组件中写入的表单

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

vuex:

适合大型项目

props:

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

eventBus

bus皆为导入的bus实例

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

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

问题:

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

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

解决的问题

通信组件需同时存在?数据在bus上存储,所以没有要求。
多次绑定?绑定监听都在bus上,不会重复绑定。
数据只在$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直接赋值也是可以的,那么为什么不这么做呢?
其实这种eventBus就是简化版的vuex。
vue文档中有这样一段话:

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

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


$emit,$on,$off 销毁

关于 事件 的 激活与销毁 来自github上Vue作者尤大大关于这问题的解答:
vm.$on() from within components stores component state in vm but doesn’t remove it when destroyed

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值