反应对象不更新手表发出的事件

reactive object not updating on event emitted from watch

我正在使用这个反应对象构建一个复杂的表单

    const formData = reactive({})
    provide('formData', formData)

在表单中,其中一个组件呈现如下:

      <ComboZone
          v-model:municipality_p="formData.registry.municipality"
          v-model:province_p="formData.registry.province"
          v-model:region_p="formData.registry.region"
        />

这是 ComboZone 渲染函数:

     setup(props: any, { emit }) {
        const { t } = useI18n()
    
        const { getters } = useStore()
        const municipalities = getters['registry/municipalities']
        const _provinces = getters['registry/provinces']
        const _regions = getters['registry/regions']
    
        const municipality = useModelWrapper(props, emit, 'municipality_p')
        const province = useModelWrapper(props, emit, 'province_p')
        const region = useModelWrapper(props, emit, 'region_p')
    
        const updateConnectedField = (key: string, collection: ComputedRef<any>) => {
          if (collection.value && collection.value.length === 1) {
            console.log(`update:${key} => ${collection.value[0].id}`)
            emit(`update:${key}`, collection.value[0].id)
          } else {
            console.log(`update:${key} =>undefined`)
            emit(`update:${key}`, undefined)
          }
        }
    
        const provinces = computed(() => (municipality.value ? _provinces[municipality.value] : []))
        const regions = computed(() => (province.value ? _regions[province.value] : []))
    
        watch(municipality, () => updateConnectedField('province_p', provinces))
        watch(province, () => updateConnectedField('region_p', regions))
    
        return { t, municipality, province, region, municipalities, provinces, regions }
      }

使用模型包装器:

import { computed, WritableComputedRef } from 'vue'
export default function useModelWrapper(props: any, emit: any, name = 'modelValue'): WritableComputedRef<any> {
  return computed({
    get: () => props[name],
    set: (value) => {
      console.log(`useModelWrapper update:${name} => ${value}`)
      emit(`update:${name}`, value)
    }
  })
}

问题是从 useModelWrapper 发出的事件正确地更新了父模板中的 formData,从 watch 函数内部发出的事件被一个渲染延迟了....

尝试在组件中使用key:prop。我认为它会解决问题。

TL;DR;

使用watchEffect代替watch


...请注意,我没有尝试重现,我的猜测是您 运行 遇到了这个问题,因为您使用的 watch 运行 懒惰地惰性 性质是延迟执行的结果,这可能是您看到它在下一个周期触发的原因。

watchEffect

Runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies are changed.

watch

Compared to watchEffect, watch allows us to:

  • Perform the side effect lazily;
  • Be more specific about what state should trigger the watcher to re-run;
  • Access both the previous and current value of the watched state.

找到了解决方案,watchEffect 不是办法。 看起来是同一个滴答中的多个更新事件的问题,对我来说,使用 { flush: 'post' } 作为手表功能的选项来处理手表的刷新。