簡體   English   中英

Vue 中的 Immer 數據未更新

[英]Immer data not updating in Vue

我正在嘗試將 Immer 與 Vue 一起使用。 似乎狀態正在更新,但 Vue 沒有更新 UI

// 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
}
<!-- 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 顯示 items 數組正在發生變化,但 Vue 模板中的 items 只是顯示一個空數組。 我怎樣才能使它在 Vue 中可見?

計算的屬性會被緩存,並且在關聯的組件數據更改之前不會重新計算它們。 由於 Immer 對象不是組件的一部分,因此永遠不會發生重新計算。

可以通過使用 getter 方法而不是計算屬性來防止緩存:

{{ getItems() }}

...

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

更直接的方法是強制重新計算屬性:

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-recomputed使用了類似的使用Vue.util.defineReactive internal 的方法。

此問題與 Immer 無關。 vuejs 緩存計算的屬性,因此當您的數據更新時它們不會更新。 這在https://v2.vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods的 vuejs 文檔中明確提到

我們可以將相同的函數定義為方法,而不是計算屬性。 對於最終結果,這兩種方法確實完全相同。 但是,不同之處在於,計算屬性是根據它們的反應依賴來緩存的。 計算屬性僅在其某些反應性依賴項發生更改時才會重新評估。

由於 Immer 不是響應式依賴項,因此計算屬性永遠不會再次運行。

解決方案是將計算屬性更改為方法。 這樣它就不會被緩存,並且該方法每次都會以更新的值運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM