微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Vuex 4 Mutate 具有相同值的初始状态不会触发观察者 更新破解

如何解决Vuex 4 Mutate 具有相同值的初始状态不会触发观察者 更新破解

因此,我尝试使用相同的值更改初始状态并且观察者不执行,如果值不同,则它按预期工作。

状态:

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',})

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,那么它就起作用了,所以我在想,也许,有办法强制这样做吗?

解决方法

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

据我所知,负责从服务器检索数据的观察者应该由 activePage itemsPerPage 的更改触发(因为我打赌它同时使用了这些值以获得正确的数据...)

幸运的是您watch允许watching multiple sources

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 更改时,您都希望将 itemsPerPage 重置为 1。但是,当您可以将此逻辑作为 globals/setItemsPerPage 突变的一部分时,为什么要对观察者执行此操作?

itemsPerPange 发生变化时,还有一些其他的事情要做,但即使没有,又有什么区别?

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

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

破解

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

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

,

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

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

这会在一开始就运行你的观察者。因此,如果您已经添加了您的值并再次运行,它应该采用与 newValue 完全相同的值。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?