如何停止 Vue.js 3 watch() API 在退出时触发

How to stop Vue.js 3 watch() API triggering on exit

我在显示产品信息的 Vue 组件中实现了 watchwatch 监视 vue-routerroute 对象,以便 ProductID 参数发生变化。当它发生变化时,我想从后端获取产品详细信息API。

要观看 route,我在 Product.vue 中这样做:

import { useRoute } from 'vue-router'

    export default {
      setup() {
        const route = useRoute();

        async function getProduct(ProductID) {
          await axios.get(`/api/product/${ProductID}`).then(..do something here)
        }
    
        // fetch the product information when params change
        watch(() => route.params.ProductID, async (newID, oldID) => {
            await getProduct(newId)
          },
          //watch options
          {
          deep: true,
          immediate: true
          }
        )
      },
    }

以上代码有效,除了如果用户离开 Product.vue,例如使用后退按钮返回主页,watch 会再次触发并尝试使用 undefined 作为 ProductID 调用 API(因为主页 route 上不存在 ProductID 参数)例如http://localhost:8080/api/product/undefined。这会导致在应用程序中抛出错误。

  1. 为什么当用户离开 Product.vue 时会触发 watch
  2. 如何正确预防?我可以使用 if(newID) { await getProduct(newId) } 来做到这一点,但它似乎与 watch 应该做的事情有悖常理。
  1. watch 在 vue 内部但独立于组件的对象中注册观察者。我认为这是 Map。所以破坏组件对反应系统没有影响

  2. 只要忽略 newIDundefined 的情况,就像您已经做的那样。但是为了防止将代码包装在一个大的 if 块中,只需在回调的开头使用 if(newID === undefined)return; 即可。如果你的 ID 总是真实的(0"" 是无效的 ID)你甚至可以使用 if(!newID)return;.

我运行陷入同样的​​问题。不用观察当前路由,而是使用 vue-router onBeforeRouteUpdate,只有当路由改变并且相同的组件被重用时才会调用它。

来自https://next.router.vuejs.org/guide/advanced/composition-api.html#navigation-guards

import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import { ref } from 'vue'

export default {
  setup() {
    // same as beforeRouteLeave option with no access to `this`
    onBeforeRouteLeave((to, from) => {
      const answer = window.confirm(
        'Do you really want to leave? you have unsaved changes!'
      )
      // cancel the navigation and stay on the same page
      if (!answer) return false
    })

    const userData = ref()

    // same as beforeRouteUpdate option with no access to `this`
    onBeforeRouteUpdate(async (to, from) => {
      // only fetch the user if the id changed as maybe only the query or the hash changed
      if (to.params.id !== from.params.id) {
        userData.value = await fetchUser(to.params.id)
      }
    })
  },
}