Vue 組件通訊的解決方案

數據通訊

首先, 咱們一般說數據傳遞, 組件通訊什麼什麼的, 我認爲能夠分紅兩種場景:javascript

  • 頁面和頁面之間vue

  • 組件和組件之間java

通訊方案

無論什麼場景, 在使用 Vue 的時候, 通常咱們有下面 5 種選擇去實現數據通訊.vuex

  1. vuex緩存

  2. storagesession

  3. props函數

  4. eventthis

  5. URL queryStringurl

選擇通訊方案

咱們在選擇通訊方案的時候, 好比說肯定 列表頁如何把每一項的 id 傳遞給 詳情頁的時候,
通常要考慮什麼問題? 你是直接全套都是 vuex, 仍是說喜歡使用 sessionStorage?code

通常咱們要考慮下面的幾個問題:

  1. 頁面是否能夠刷新

  2. 頁面是否能夠分享 (或者說URL 是否要求 RESTful)

  3. 數據更新以後, 全部使用此數據的組件是否都須要響應更新

分析

先說 '頁面和頁面之間的通訊場景', 首先上面的 5 種方案, 咱們可選的有:

vuex, storage, URL queryString.

而後分析一下, 每一種方案, 它對上面的 3個問題, 是否是很好的解決掉了:
備註:
頁面通訊場景不會要求實時響應, 由於就算下個頁面的確是實時響應, 你也看不見,
因此主要看 '刷新' 和 '分享'

vuex: 不能刷新, 不能分享
storage: 不能分享
url: 能刷新, 能分享

這樣看來, url queryString 的方式是 '頁面通訊場景' 中的最佳選擇, 可是我依舊有疑慮:

  1. 我始終以爲把跳轉信息, 暴露給用戶, 是很很差的事情; (心理問題, 能夠克服)

  2. url 的長度限制; 這個無所謂的, 2k, 你再怎麼傳遞, 我都不會以爲你會出現超過 2k 的狀況

  3. url 須要拼接, 這個拼接是否麻煩? 也不麻煩, 只是對象轉字符串.

  4. 這樣每一個頁面都須要在進入的時候先解析一下 queryString, 這樣是否是增長了麻煩的程度
    也能夠經過 mixins 來操做. 聚合到 mixins, 何況也不必定不少.

因此咱們能夠選擇 'url queryString' 做爲 '頁面和頁面通訊場景' 中的通訊方案.
之後你就能夠這樣用了:

好比列表頁面跳轉到詳情頁要帶一個 id

this.$router.push({
        path: 'detail',
        query: {
            id
        }
    })

你的 url 會始終長這樣:

https://abc.com/#/?id=123

備註: 若是你的頁面不能刷新和分享, 你徹底能夠三種方案隨便選, 愛誰誰.

重點: url queryString 的方式, 有一個問題解決不了:

從詳情頁到訂單頁, 經過 queryString 帶了商品信息過來, 假設此時 url 長這樣:
    order/?goods=xxx
訂單頁面有一個收貨地址欄, 點擊能夠進入地址編輯頁面, 此時的 url 不會帶參數的(你能夠試試帶一下看多麻煩)
    address-edit/
地址編輯頁面有一個保存按鈕, 點擊會返回到訂單頁面
    order/

so, url queryString 丟了.

我目前的解決方案:
針對這種存在多入口的頁面, 必定要在進入它的第一時間, 先把 queryString 存起來.
而且作以下判斷:

if (// 存在 queryString) {
    // use queryString
} else {
    // use storage
}

可是這種方式仍是搞不定 從地址編輯頁返回到訂單頁, 用戶此時分享訂單頁, 分享出去的玩意確定會是錯的.


如今來講下 '組件和組件之間的通訊場景'
上面的 5 種方案, 能夠選擇 vuex, event, props, storage

先看下 刷新, 分享和實時響應
vuex, 不能刷新
event, props 能刷新能分享
storage 不能分享 & 實時.

解釋:
爲何 vuex 在這裏仍是不能刷新
由於若是使用的 state 裏面的值是其餘頁面設置的而不是 init 就存在的, 刷新丟值.
爲何 event, props 能夠作到防刷新防分享
由於這兩個玩意是程序運行它就生效的, 它也能夠作到實時更新.
storage 雖然在存的時候有一個事件, 可是這太 trick 了.

因此咱們選擇的是 event, props?

分析一下吧.
組件通訊能夠分紅兩種, 父子, 同輩.

父子之間呢:
父傳子: props
子傳父: $emit(event)

這就是 'props down, events up';

可是其實還有:
父傳子: this.$refs.xxx
子傳父: this.$parent.xxx

還有: 自定義 v-model

還有: 讓 props 是一個對象.

同輩之間: event-bus.

因此這就完了? 啥都沒有了? 嗯, 就這樣.

思考

  1. 關於 vuex 的應用場景的考慮
    不是應該全部的組件, 路由之間的數據傳遞都應該經過 vuex, 當同時存在兩種方式能夠選擇的時候,選擇 vuex 的惟一理由只有一個:

    須要響應式的狀態

    why?

    由於 vuex 雖然有輔助函數, 可是用起來仍是要 引入, 定義. 並且真的是一刷新頁面就掛了.
  2. 能夠經過監聽 beforeunload 事件, 在其中緩存 state, 而後在 onload 事件再恢復, 這樣能夠避免掉vuex 的丟值.

  3. 沒有必要追求全項目統一的一種通訊方式, 理論上你不考慮刷新分享, 全項目都用 vuex, 什麼事情也不會有的.

  4. vuex 是狀態管理, 不是保存常量的地方.

相關文章
相關標籤/搜索