資料通訊
首先, 我們通常說資料傳遞, 元件通訊什麼什麼的, 我認為可以分成兩種場景:
-
頁面和頁面之間
-
元件和元件之間
通訊方案
不管什麼場景, 在使用 Vue 的時候, 一般我們有下面 5 種選擇去實現資料通訊.
-
vuex
-
storage
-
props
-
event
-
URL queryString
選擇通訊方案
我們在選擇通訊方案的時候, 比如說確定 列表頁如何把每一項的 id 傳遞給 詳情頁的時候,
一般要考慮什麼問題? 你是直接全套都是 vuex, 還是說喜歡使用 sessionStorage?
一般我們要考慮下面的幾個問題:
-
頁面是否可以重新整理
-
頁面是否可以分享 (或者說URL 是否要求 RESTful)
-
資料更新之後, 所有使用此資料的元件是否都需要響應更新
分析
先說 `頁面和頁面之間的通訊場景`, 首先上面的 5 種方案, 我們可選的有:
vuex, storage, URL queryString.
然後分析一下, 每一種方案, 它對上面的 3個問題, 是不是很好的解決掉了:
備註:
頁面通訊場景不會要求實時響應, 因為就算下個頁面的確是實時響應, 你也看不見,
所以主要看 `重新整理` 和 `分享`
vuex: 不能重新整理, 不能分享
storage: 不能分享
url: 能重新整理, 能分享
這樣看來, url queryString 的方式是 `頁面通訊場景` 中的最佳選擇, 但是我依舊有疑慮:
-
我始終覺得把跳轉資訊, 暴露給使用者, 是很不好的事情; (心理問題, 可以克服)
-
url 的長度限制; 這個無所謂的, 2k, 你再怎麼傳遞, 我都不會覺得你會出現超過 2k 的情況
-
url 需要拼接, 這個拼接是否麻煩? 也不麻煩, 只是物件轉字串.
-
這樣每個頁面都需要在進入的時候先解析一下 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.
所以這就完了? 啥都沒有了? 嗯, 就這樣.
思考
-
關於 vuex 的應用場景的考慮
不是應該所有的元件, 路由之間的資料傳遞都應該通過 vuex, 當同時存在兩種方式可以選擇的時候,選擇 vuex 的唯一理由只有一個:需要響應式的狀態
why?
因為 vuex 雖然有輔助函式, 但是用起來還是要 引入, 定義. 而且真的是一重新整理頁面就掛了.
-
可以通過監聽 beforeunload 事件, 在其中快取 state, 然後在 onload 事件再恢復, 這樣可以避免掉vuex 的丟值.
-
沒有必要追求全專案統一的一種通訊方式, 理論上你不考慮重新整理分享, 全專案都用 vuex, 什麼事情也不會有的.
-
vuex 是狀態管理, 不是儲存常量的地方.