首页 > 解决方案 > Vue3 Composition API watcher 立即触发,但它应该是惰性的

问题描述

根据 vue3 docs,默认情况下观察者应该是惰性的,但我的会立即触发。我有一个父表单,我在其中发出 axios 请求以从 db 检索类别列表,然后我将它们作为道具数据发送到子 select2 输入(是的,jquery 之一)。

父窗体.vue:

<template>
 <VSelect2 :data="categories" @item-added="getCategories()"/>
</template>
<script>
export default {
 name: "Form",
 setup() {
    let categories = ref([])
    const getCategories = async () => {
      const response = await httpClient.get('/api/categories')
      response.data.forEach(category => {
        categories.value.push({
          id: category.id,
          text: category.title,
        })
      })
    }
    getCategories()
    return {
      categories
    }
 }
}
</script>

VSelect2.vue:

<template>
 <select
    class="vue-select2"
  >
</template>
<script>
import {
  onMounted,
  watch
} from 'vue'
export default {
 name: "VSelect2",
 props: {
   data: {
      type: Array,
      required: true
    }
 },
 setup(props) {
    onMounted(() => {
      $(document).ready(function () {
        $('.vue-select2').select2({
          multiple: true,
          tags: true,
          allowClear: true,
          tokenSeparators: [',', ' '],
          data: props.data,
        }).on('select2:select', function (event) {
              //when user adds an item, make a post request then emit event for the parent to retrieve the new data
              ...
              emit('item-added')
        })
     })
    })

    watch(props.data, (newValue) => {
      console.log(newValue)
    })

    return {
    }
 }
}
</script>

github上有一个问题,它说这是预期的行为,但文档说不然......我有点困惑。有谁知道我是否可以以某种方式将其设置为懒惰?通过{immediate: false}{lazy:true}作为监视选项什么都不做......

标签: jquery-select2watchvuejs3

解决方案


好吧,我无法重现您在这里所说的内容。请看下面的简单示例。回调仅在watch值更改时调用一次(在 2 秒后模拟异步调用) -它是惰性的

const App = {
  template: '<comp :data="categories"></comp>',
  setup() {
    let categories = Vue.ref([])
    const getCategories = async() => {
      return new Promise(resolve => setTimeout(() => {
        categories.value.push({
          name: "Category A"
        })
        resolve()
      }, 2000));
    }
    getCategories()

    return {
      categories
    }
  }
}

const app = Vue.createApp(App)

app.component('comp', {
  props: {
    data: {
      type: Array,
      required: true
    }
  },
  template: `<h4>{{ data }}</h4>`,
  setup(props) {
    Vue.watch(props.data, (newValue) => {
      console.log("New value:", newValue)
    })

    return {}
  }
})

app.mount("#app")
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.7/vue.global.js" integrity="sha512-+i5dAv2T8IUOP7oRl2iqlAErpjtBOkNtREnW/Te+4VgQ52h4tAY5biFFQJmF03jVDWU4R7l47BwV8H6qQ+/MfA==" crossorigin="anonymous"></script>
<div id="app"></div>

至于链接的 GH问题- 您应该非常小心共享作为预发布版本报告的问题的一部分的所有信息(在这种情况下为“alpha 4”)。如果你阅读了整个讨论,你会发现这个问题导致了新RFC的创建,并且作为讨论的结果,他们后来改变了问题中描述的行为,以便watch保持惰性评估与 Vue 2 兼容(来自问题的观点,即作者要求的更改)并watchEffect引入了新的 API(即“渴望”)

Vue 3 现已发布,因此官方文档应该是您的主要信息来源,而不是非常过时的预发布版本的 GH 问题...


推荐阅读