1

所以,我尝试用相同的值更改初始状态并且观察者不执行,如果值不同,那么它会按预期工作。

状态:

const state = () => ({
  pagination: {
    activePage: 1,
    itemsPerPageOptions: [
      { label: 1, value: 1 },
      { label: 2, value: 2 },
      { label: 3, value: 3 },
      { label: 16, value: 16 },
      { label: 24, value: 24 },
      { label: 32, value: 32 },
      { label: 40, value: 40 },
    ],
    itemsPerPage: 2,
  },
})

//对于每个状态我都有一个getter和一个setter(mutation)

const itemsPerPage = computed({
  get: () => store.getters['globals/getItemsPerPage'],
  set: value => store.commit('globals/setItemsPerPage', value),
})

let activePage = computed({
  get: () => store.getters['globals/getActivePage'],
  set: value => store.commit('globals/setActivePage', value),
})

watch(itemsPerPage, () => {
  //some work

  store.commit('globals/setActivePage', 1)
  //or change the computed prop directly with activePage.value = 1
})

在上面的组件中,当 itemPerPage 值更改时,我通过将 activePage 设置为 1 来重置分页。在另一个组件中,我有一个观察者,它根据 activePage 从服务器检索数据:

watch(activePage, page => {
  //get data from server
})

它不是这样工作的,但是如果我将 activePage 的初始状态更改为 2,那么它就可以工作,所以我在想,也许有办法强制这样做?

4

2 回答 2

0

好吧,观察者只有在它正在观察的值发生变化时才会触发。将ref(或计算的可写引用)设置为 1 到 1 将永远不会运行观察者,也没有办法强制它......

据我了解,负责从服务器检索数据的观察者应该由两者的更改触发,activePage 并且 itemsPerPage(因为我打赌它使用这两个值来获取正确的数据......)

幸运的是,您watch可以观看多个来源

watch([activePage, itemsPerPage] , (newValues) => {
  // newValues[0] = new value of activePage
  // newValues[1] = new value of itemsPerPage

  // or with destructuring
  [newActivePage, newItemsPerPage] = newValues
  
  // ...get data from server
})

更新

对,但问题是我最终发送了两个请求

好吧,那一定是问题中未显示的代码中的其他内容。如果你看下面的例子,第二个观察者只执行一次(当然,我的例子没有使用 Vuex,但这应该没有什么区别)

const app = Vue.createApp({
  setup() {
    const activePage = Vue.ref(1)
    const itemsPerPage = Vue.ref(10)

    Vue.watch(itemsPerPage, (value) => {
      console.log(`itemsPerPage changed: ${value}`)
      activePage.value = 1
    })

    Vue.watch([itemsPerPage, activePage], (newValues) => {
      [newItemsPerPage, newActivePage] = newValues
      console.log(`Requesting data from server (itemsPerPage: ${newItemsPerPage}, activePage: ${newActivePage})`)
    })

    Vue.onUpdated(() => console.log(`component updated`))

    return {
      activePage,
      itemsPerPage,
    }
  }
})
app.mount("#app")
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.11/vue.global.prod.js" integrity="sha512-v+zXKcc6SpL6LiZLwCzxijGutXrQ4tulM1X1IRWchA8gliet94/xz3OWeXDgEyPkvS3MLxwKwpceuJoUBc9Wxg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="app">
  <div> activePage: {{ activePage }} </div>
  <div> <button @click="activePage++">Update activePage</button></div>
  <div> itemsPerPage: {{ itemsPerPage }} </div>
  <div> <button @click="itemsPerPage++">Update itemsPerPage</button></div>
</div>

只是一个想法:您希望在更改activePage时重置为 1 itemsPerPage。但是,当您可以将此逻辑作为globals/setItemsPerPage突变的一部分时,为什么还要使用 watcher 呢?

更改后还有其他一些事情要做itemsPerPange,但即使没有,那会有什么不同呢?

最大的不同是这两种变化是同时发生的,而不是在两个独立的观察者身上。对于未来的程序员来说,这也更加清晰,因为他可以立即看到正在发生的事情。

您仍然可以保留第一个观察者(做“其他事情”),只需将activePage突变移动到globals/setItemsPerPage

哈克

只是为了完整 - 这是一个我不喜欢和推荐的解决方案,但你会在 SO 上的许多“反应性问题”答案中找到它。

只需创建辅助变量 - 例如key = 0。每当您将 重置activePage为 1 时,递增key1。在您的第二个观察者中,同时观察activePagekey

于 2021-06-02T16:37:44.907 回答
0

如果您希望观察者立即运行,您可以向观察者添加第二个参数,如下所示:

watch(() => {...}, {immediate: true})

这将在一开始就运行你的观察者。因此,如果您已经增加了您的价值并且它再次运行,它应该采用与newValue.

如果您希望在值设置为完全相同的值时将其作为一个通用的“过程”来运行您的观察程序,您将需要像 Michal 已经建议的辅助函数之类的东西。

于 2021-06-07T06:10:31.033 回答