vue.js - 如何在 Vue3 中使用单个观察者观察 ref 和 reactive 对象

标签 vue.js watch vuejs3

Vue v3 docs显示了通过将数组作为参数传递给单个观察者来观察多个引用的示例

我能否(以及如何)使用类似的方法通过单个观察者同时观察 refreactive 对象?

const state = reactive({
  postPerPage: 10,
  currentPage: 1,
});

const posts = ref([]);

const currentPosts = ref([]);

watch(
  () => posts.value, // store value in currentPosts when the posts.value is updated (get data from api)
  () => {
    currentPosts.value = getCurrentPost(); 
  }
)

watch(
 () => {
  return { ...state };
 }
 () => {
  currentPosts.value = getCurrentPost();
 }
)

最佳答案

docs中的例子不是很清楚但是当你将一个数组作为第一个参数传递(以观察多个源)时,该数组可以包含函数和裸引用的混合。请参见下面的示例。

const app = Vue.createApp({  
  setup() {
    const state = Vue.reactive({
      postPerPage: 10,
      currentPage: 1,
    });

    const posts = Vue.ref([]);
    
    const normalRef = Vue.ref(0)
    
    const watchCounter = Vue.ref(0)

    Vue.watch([
        //() => posts.value, // <-- this will not trigger watch callback on array push (only on array replace). Can be fixed by deep watch (uncomment last argument of watch)
        //posts, // <-- same result as above
        () => [ ...posts.value],         
        // () => state, // similar to array, this does not trigger on property change
        () => ({ ...state }), 
        normalRef
      ],
      (newValues, prevValues) => {
        watchCounter.value++
        console.log(`prev (${watchCounter.value}):`, prevValues);
        console.log(`new (${watchCounter.value}):`, newValues);
      },
      // { deep: true }
    )
    
    return {
      state,
      posts,
      normalRef,
      watchCounter
    }
  },
  mounted() {
    const interval = 1000
    setTimeout( () => this.state.currentPage = 2, interval)
    setTimeout( () => this.posts.push({ a: 1 }), interval*2)    
    setTimeout( () => this.normalRef = 10, interval*3)    
  }
})

app.mount("#app")
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.11/vue.global.js" integrity="sha512-1gHWIGJfX0pBsPJHfyoAV4NiZ0wjjE1regXVSwglTejjna0/x/XG8tg+i3ZAsDtuci24LLxW8azhp1+VYE5daw==" crossorigin="anonymous"></script>

<div id="app">
  <div>Watch counter {{ watchCounter }}</div>
  <div>{{ state }}</div>
  <div>{{ posts }}</div>
  <div>{{ normalRef }}</div>
</div>

其他方法当然是继续使用两个观察者并将回调功能重构为单独的函数....

const callback = () => {
  currentPosts.value = getCurrentPost();
}

watch(() => ({ ...state }), callback)

关于vue.js - 如何在 Vue3 中使用单个观察者观察 ref 和 reactive 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67072402/

相关文章:

linux - 使用 "watch"在 Bash 中重复运行一个函数?

vue.js - Vue 模块组件检测 Vue.js 版本?

vue.js - 无法使用$ http或Vue.http

vue.js - 如何使用 Nuxt 和 asyncData 观察路由变化

vue.js - Vue JS - 当其中使用的字段更新时,如何观察计算触发它?

javascript - 如果没有 $scope.digest,$watch 不会触发

javascript - 基于 vue 3 中计算的另一个计算的更改

typescript - Vue.js 3 : props type validation with custom type

javascript - 如何通过 vue router 将对象作为 prop 传递

javascript - 如何使用vue动态添加before after css代码?