如何在 Vuex 中存储非响应式数据?

Posted

技术标签:

【中文标题】如何在 Vuex 中存储非响应式数据?【英文标题】:How to store non-reactive data in Vuex? 【发布时间】:2018-05-07 05:40:53 【问题描述】:

我有数据,在 VueJS 应用程序初始化之前在页面上加载一次,并且该数据不会一直更改,而 html 页面不会重新加载(经典 CGI 应用程序,而不是 SPA)。数据示例:

const nonReactiveObjectWithSomeNestedData = 
  a: 'a',
  b: 
    bb: 'bb',
    cc:  ccc: 'ccc' ,
    dd: ['dd1', 'dd2']
  

我在几个 vue 组件中使用了这些数据。将这些数据存储在 Vuex 命名空间模块中并使用 Vuex-getter 为不同的 vue 组件包装相同的功能会很方便。有没有办法将这些数据存储在 vuex state 之外(不需要反应性)但能够从 vuex-module 的 getter 访问?

PS. 目前我正在使用存储非反应性数据inside vue-instance 方法,但现在还不够,我需要更多全局访问数据(来自两个独立的根组件)。

【问题讨论】:

【参考方案1】:

在突变文件中,您可以深度克隆您不想反应的有效负载

import _ from 'lodash';

    [mutationTypes.SET_INITIAL_STATE](state, payload) 
    // In order to make sure that this property is non-reactive deep clone it
    state.initialState = _.cloneDeep(payload)

这样,initialState 或您添加到状态的任何属性都不会是响应式的。

【讨论】:

【参考方案2】:

我可以通过这样做来消除“反应性”

// create new variable and remove reactiveness, does a deep clone
var someNewNonReactiveVar = JSON.parse(JSON.stringify(someReactiveVar));

【讨论】:

【参考方案3】:

还可以向对象添加属性_isVue 以避免使其反应。

commit('setNonReactiveObject', Object.assign(data,  _isVue: true )

当无法控制数据在存储中的存储方式时,此方法可用于使数据不响应。例如,当存储数据被客户端完全替换以“水合”服务器端呈现的网站(例如 Nuxt)时。

这是未记录的,将来可能会中断。 至少source code 有一个注释,表明此属性在内部用于此目的。 here 是在观察对象之前检查属性的位置。

【讨论】:

【参考方案4】:

在将对象添加到商店之前冻结它:

Object.freeze(nonReactiveObjectWithSomeNestedData )

Vue 不会使冻结的对象反应。

注意:您应该在对象进入 Vuex 突变/动作之前将其冻结:

this.$store.dispatch('moduleName/setNonReactiveObject', 
    Object.freeze(nonReactiveObjectWithSomeNestedData));

在变异函数内部,有效载荷参数已经是反应性的。

【讨论】:

如果我们稍后需要更改该对象但仍不想要反应性怎么办? 1.制作副本const copy = ..original ,2. 更改该副本,3. 冻结副本,4. 用副本替换商店中的原件。 现在我正在使用 vuex 3.0.1 并且有效载荷参数在动作和突变函数内部不是“已经反应”(但当然是之后)。

以上是关于如何在 Vuex 中存储非响应式数据?的主要内容,如果未能解决你的问题,请参考以下文章

vue源码之响应式数据

vue3修改响应式代理值

关于数组的响应式方法和非响应式方法

vuex

vuex 使用Store存储共享数据时,需要考虑逻辑上要不要响应Store值的变化

vuex 与 vue有啥区别