Vue 3 在元素添加到数组时重新运行计算

问题描述 投票:0回答:1

我有一个文档对象,在可组合项中通过

id
进行管理,同时向外部显示
computed
(派生,只读)状态:

const state = reactive({})

export const useDocs = () => {
  return {
    create: doc => { state[doc.id] = doc },
    read: computed(() => Object.values(state)),
    update: (id, val) => {
      Object.assign(state[id], val)
    },
    delete: (id) => { delete state[id] },
  }
}

但是,如果没有

显式刷新
,我无法让 computed 重新运行,我想避免这种情况,因为我认为必须有一个有效的全响应式解决方案。

const { create, read } = useDocs()

watch(() => read, docs => {
  console.debug('change detected') // runs only initially
})

// ... later
create({ id: 1, foo: 'bar' }) // not reflected in watcher

我还想避免任何引用以使其可跨模板组合。

vuejs3 vue-composition-api vue-reactivity
1个回答
0
投票

出现此问题是因为 Vue 的反应性系统无法自动跟踪普通反应性对象上的属性添加/删除。您可以在这里阅读 moare 的相关内容:

https://vuejs.org/guide/essentials/reactivity-fundamentals.html#limitations-of-reactive

https://vuejs.org/api/reactivity-core.html#reactive

https://codepen.io/mvsde/pen/abNOKOB

https://www.w3schools.com/jsref/jsref_map_new.asp

我的方法是使用 Map 而不是普通对象 - Map 的方法(如

set()
delete()
)由 Vue 的反应性系统跟踪,使每个文档在存储时具有反应性,并使用
Array.from(state.values())
来从地图正确导出

import { reactive, computed } from 'vue'

export const useDocs = () => {
  // Using Map instead of plain object for better reactivity
  const state = reactive(new Map())

  return {
    create: (doc) => {
      state.set(doc.id, reactive(doc))
    },
    read: computed(() => Array.from(state.values())),
    update: (id, val) => {
      const doc = state.get(id)
      if (doc) {
        Object.assign(doc, val)
      }
    },
    delete: (id) => {
      state.delete(id)
    },
    // Optional: Get single document
    getDoc: (id) => computed(() => state.get(id))
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.