道具手表在 Vue 组合中不起作用 api

Props watch not working in Vue composition api

我有一个 state 对象作为道具从另一个组件传递。我收到了预期的 state。然后我将 props 存储在 toRef() 中以进行反应。

我想要发生的是当state中的数据改变时,我想更新浏览器中的数据。就像现在一样,数据确实在 vue 开发工具中得到了更新,我确实看到 state 对象发生了变化,但是浏览器在我手动刷新浏览器之前不会反映这些变化,这是一个不希望的结果。

为什么会这样:

组件:

<template>
      <div class="show-products">
        <Product
            v-for="data in products"
            :key="data.id"
            :product="data"
        />
      </div>
 </template>

<script>
import {computed, onMounted, toRefs, watch } from "vue";
import {useStore} from "vuex";
    
    export default {
      components: {Product},
      props: {
        state: Object
      },
      setup (props) {
        const store = useStore();
        const products = computed(() => store.getters.getProducts);
    
        let stateRef = toRefs(props).state;
    
        onMounted(() => {
          store.dispatch('getProducts');
        });
    
        watch(stateRef, (currentState, prevState) => {
          if (currentState.length !== prevState.length) {
            store.dispatch('getProducts');
          }
        })
    
        return {
          Product,
          products,
        }
      }
    }
</script>

观察数组长度需要深度观察者,所以一定要设置deep标志:

watch(stateRef, (currentState, prevState) => {/*...*/}, { deep: true })

此外,观察者回调只接收数据引用,所以如果你只是改变原始数组(例如,通过 push()pop()),currentStateprevState 参数将是相同的引用,这将导致长度差异检查失败。

一个可能的解决方案是删除长度检查,并始终在观察者中调度 getProducts 操作:

// ProductList.vue
watch(stateRef, (currentState, prevState) => {
  store.dispatch('getProducts')
}, { deep: true })

另一种不需要深度观察者的解决方案是分配一个新数组给 state,而不是在原始数组上使用 push()/pop()

// Parent.vue
addState(newValue) {
  state.value = [ ...state.value, newValue ]
}

demo