数据通信
首先, 我们通常说数据传递, 组件通信什么什么的, 我认为可以分成两种场景:
页面和页面之间
组件和组件之间
通信方案
不管什么场景, 在使用 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 是状态管理, 不是保存常量的地方.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。