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 是状态管理, 不是保存常量的地方.

相关文章
相关标签/搜索