[英]VueJS 3: update value and avoid watch
I am coding a table with pagination component, and I use multiple v-model and watch
on these variables to fetch the data.我正在编写一个带有分页组件的表格,我使用多个 v-model 并
watch
这些变量来获取数据。 When perPage
is updated, I want to reset page
to 1. So I did it in my watch
method but of course, watch
is triggered twice (for perPage
and then page
).当
perPage
更新时,我想将page
重置为 1。所以我在watch
方法中这样做了,但是当然, watch
被触发了两次(对于perPage
,然后是page
)。
Is it possible to update the variable and disable watch at this moment?此时是否可以更新变量并禁用手表?
Here is my current code:这是我当前的代码:
<script setup lang="ts">
const sort = ref(route.query.sort || 'created_at')
const filters = ref(route.query.filters || {})
const page = ref(route.query.page ? parseInt(route.query.page.toString()) : 1)
const perPage = ref(route.query.per_page ? parseInt(route.query.per_page.toString()) : 10)
watch([sort, filters, page, perPage], ([oldSort, oldFilters, oldPage, oldPerPage], [newSort, newFilters, newPage, newPerPage]) => {
if (oldPerPage !== newPerPage)
page.value = 1
fetchItems()
router.push({
query: {
...route.query,
sort: sort.value,
// filters: filters.value,
page: page.value,
per_page: perPage.value,
},
})
})
async function fetchItems() {
items.value = await userApi.list({
filters: toRaw(filters.value),
sort: sort.value,
page: page.value,
perPage: perPage.value,
})
}
</script>
<template>
<CTable
:pagination-enabled="true"
v-model:sort="sort"
v-model:page="page"
v-model:per-page="perPage"
:total-items="items.meta.total"
:total-pages="items.meta.last_page"
/>
</template>
The only workaround I found is to return when I reset page
:我发现的唯一解决方法是在我重置
page
时返回:
watch(..., () => {
if (oldPerPage !== newPerPage) {
page.value = 1
return
}
fetchItems()
...
})
It is working in my case but for some another cases I would like to update without trigger the watch method.它适用于我的情况,但对于其他一些情况,我想在不触发 watch 方法的情况下进行更新。
Thanks!谢谢!
Create another watcher for perPage
:为
perPage
创建另一个观察者:
watch([sort, filters, page, perPage], ([oldSort, oldFilters, oldPage, oldPerPage], [newSort, newFilters, newPage, newPerPage]) => {
fetchItems()
router.push({
query: {
...route.query,
sort: sort.value,
// filters: filters.value,
page: page.value,
per_page: perPage.value,
},
})
})
watch(perPage, (newPerPage,oldPerPage ) => {
if (oldPerPage !== newPerPage)
page.value = 1
})
It's recommended to create watch for a single property separately to avoid unnecessarily updates and conflicts.建议单独为单个属性创建监视以避免不必要的更新和冲突。 For the first watch try to replace it with
watchEffect
like since you're not using the old/new value:对于第一个手表,尝试用
watchEffect
替换它,因为您没有使用旧/新值:
watchEffect(() => {
fetchItems()
router.push({
query: {
...route.query,
sort: sort.value,
// filters: filters.value,
page: page.value,
per_page: perPage.value,
},
})
})
Considering that the state is changed through v-model
, it needs to be observed with a watcher.考虑到 state 是通过
v-model
改变的,需要用 watcher 来观察。
In order to avoid a watcher to be triggered multiple times, it should implement additional conditions like shown in the question, but it also needs to not skip an update when page
is already 1
, this won't result in additional update:为了避免观察者被多次触发,它应该实现问题中显示的附加条件,但是当
page
已经是1
时它也需要不跳过更新,这不会导致额外的更新:
if (oldPerPage !== newPerPage) {
page.value = 1
if (newPage !== 1)
return
}
Otherwise there need to be multiple watchers, like another answer suggests.否则,就像另一个答案所暗示的那样,需要有多个观察者。 In case a watcher that causes asynchronous side effects (
fetchItems
) shouldn't be triggered more than it needs, and there are other causes for this to happen besides perPage
, it can be debounced, eg:如果导致异步副作用 (
fetchItems
) 的观察者不应被触发超过其需要的次数,并且除了perPage
之外还有其他原因导致这种情况发生,则可以对其进行去抖动,例如:
watch(perPage, () => {
page.value = 1
});
watch([sort, filters, page, perPage], debounce(() => {
fetchItems()
...
}, 100));
Thank you for all your answers, I finally found what I was looking for using VueUse - watchIgnorable :感谢您的所有回答,我终于找到了使用VueUse - watchIgnorable的内容:
const { stop, ignoreUpdates } = watchIgnorable(page, (value) => {
fetchItems()
})
watch(perPage, (newPerPage, oldPerPage) => {
if (newPerPage !== oldPerPage) {
ignoreUpdates(() => {
page.value = 1
})
}
fetchItems()
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.