首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Vue中未更新的Immer数据

Vue中未更新的Immer数据
EN

Stack Overflow用户
提问于 2020-02-04 13:46:17
回答 2查看 1.4K关注 0票数 2

我在试着用Immer和Vue。状态似乎正在更新,但是Vue没有更新UI

代码语言:javascript
复制
// immutable.js
import produce, { applyPatches } from "immer"

let undo_buffer = []
export var state = { items: [] }
const handle_add_patch = (patch, inverse_patches) => {
  console.log("Inverse Patches: ", inverse_patches)
  undo_buffer.push(inverse_patches)
}
export const add_item = (item_name) => {
  console.log("Starting add_item call")
  const next_state = produce(
    state,
    draft => {
      draft.items.push({ name: item_name })
    },
    handle_add_patch
  )
  console.log("next state: ", next_state)
  state = next_state
}
export const undo = () => {
  const undo_patch = undo_buffer.pop()
  if (!undo_patch) return
  let new_state = applyPatches(state, undo_patch)
  console.log("New State: ", new_state)
  state = new_state
}
代码语言:javascript
复制
<!-- item_list.Vue -->
<template>
  <div>
    <button @click.prevent="add_item()">Add Item</button>
      {{ items }}
    <button @click.prevent="undo()">Undo</button>
  </div>
</template>
<script>
import * as immutable from './immutable.js'
export default {
  computed: {
    items: function(){ return immutable.state.items }
  },
  methods: {
    add_item(){
      console.log("State Before: ", immutable.state)
      immutable.add_item("Hello")
      console.log("State After: ", immutable.state)
    },
    undo(){
      console.log("State Before: ", immutable.state)
      immutable.undo()
      console.log("State After: ", immutable.state)
    }
  }
}
</script>

console.log显示项数组正在更改,但Vue模板中的项只显示一个空数组。我怎样才能在Vue中看到这一点?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-18 10:58:16

计算的属性被缓存,在相关的组件数据被更改之前不会重新计算它们。由于Immer对象不是组件的一部分,因此不会发生重构。

可以使用getter方法而不是计算属性来防止缓存:

代码语言:javascript
复制
{{ getItems() }}

...

methods: {
  getItems: () => immutable.state.items
  addItem() {
    immutable.add_item("Hello");
    this.$forceUpdate();
  }
}

一种更直接的方法是强制重新计算一个属性:

代码语言:javascript
复制
data() {
  return { _itemsDirtyFlag: 0 }
},
computed: {
  items: {
    get() {
      this._itemsDirtyFlag; // associate it with this computed property
      return immutable.state.items;
    }
},
methods: {
  updateItems() {
    this._itemsDirtyFlag++;
  },
  addItem() {
    immutable.add_item("Hello");
    this.updateItems();
  }
}

使用Vue.util.defineReactive内部的类似方法是由vue-recomputed使用的。

票数 3
EN

Stack Overflow用户

发布于 2020-02-18 11:59:03

这个问题与Immer无关。vuejs缓存计算的属性,因此它们不会在数据更新时更新。在https://v2.vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods的vuejs文档中清楚地提到了这一点。

代替计算属性,我们可以定义与方法相同的函数。对于最终结果,这两种方法确实是完全相同的。但是,不同之处在于,计算的属性是基于它们的反应性依赖关系来缓存的。计算的属性只有在某些反应性依赖项发生更改时才会重新评估。

由于Immer不是反应性依赖项,因此计算的属性从此不再运行。

解决这一问题的方法是将计算的属性更改为方法。这样,它将不会被缓存,该方法将使用更新的值每次运行。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60058783

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档