如何停止 Vue.js 3 watch() API 在退出时触发
How to stop Vue.js 3 watch() API triggering on exit
我在显示产品信息的 Vue 组件中实现了 watch
。 watch
监视 vue-router
的 route
对象,以便 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
。这会导致在应用程序中抛出错误。
- 为什么当用户离开
Product.vue
时会触发 watch
?
- 如何正确预防?我可以使用
if(newID) { await getProduct(newId) }
来做到这一点,但它似乎与 watch
应该做的事情有悖常理。
watch
在 vue 内部但独立于组件的对象中注册观察者。我认为这是 Map
。所以破坏组件对反应系统没有影响
只要忽略 newID
是 undefined
的情况,就像您已经做的那样。但是为了防止将代码包装在一个大的 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)
}
})
},
}
我在显示产品信息的 Vue 组件中实现了 watch
。 watch
监视 vue-router
的 route
对象,以便 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
。这会导致在应用程序中抛出错误。
- 为什么当用户离开
Product.vue
时会触发watch
? - 如何正确预防?我可以使用
if(newID) { await getProduct(newId) }
来做到这一点,但它似乎与watch
应该做的事情有悖常理。
watch
在 vue 内部但独立于组件的对象中注册观察者。我认为这是Map
。所以破坏组件对反应系统没有影响只要忽略
newID
是undefined
的情况,就像您已经做的那样。但是为了防止将代码包装在一个大的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)
}
})
},
}