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架構的理解和使用也沒有那麼難不是嗎

相關文章
相關標籤/搜索