vue.js - 响应式(Reactive)对象未更新 watch 发出的事件

标签 vue.js vuejs3 vue-composition-api

我正在使用这个响应式(Reactive)对象构建一个复杂的表单

    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 函数内部发出的事件延迟了一次渲染......

最佳答案

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.

关于vue.js - 响应式(Reactive)对象未更新 watch 发出的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65796891/

相关文章:

javascript - 更改点击事件中选定的选项卡

proxy - Webpack-dev-server 不通过代理向外部域发送请求

typescript - 关于 Vue 3 + TypeScript 和 Augmenting-Types-for-Use-with-Plugins 的问题

javascript - 从 vuex 模块中监听 Action /突变

vue.js - Nuxt 和 Ag Grid 问题 SyntaxError Missing stack frames

vuejs3 - Vue 3、Composition Api 'reactive' 上的双向数据绑定(bind)无法正常工作

vue.js - Vue 组合 API : Defining emits

vue.js - pinia 在 Action 中使用 state 而不是 this

javascript - @vue-composition/如何在 setup() 中使用异步方法

javascript - 在 Options API (Vue Js) 中使用 Composition API