返回

Vue 组件中组件状态更改后计算方法不更新?快来看看两种解决方案

vue.js

Vue 组件中组件状态更改不再传播到计算方法

前言

在对 Vuex store 进行重构后,Vue 组件中的计算方法可能不再动态更新。本文将深入探讨这一问题,并提供两种有效的解决方案,以确保计算方法对 store 状态更改做出及时响应。

问题

当 store 使用 Promise 异步获取数据时,Promise 执行完后,store 状态会立即更新,从而触发计算方法的重新计算。然而,当 store 改用 async/await 异步风格时,异步操作会在事件循环的下一轮中执行,因此在计算方法执行时,store 状态尚未更新。

解决方案

为了解决这个问题,有两种解决方案:

1. 使用 Vuex Getter

Vuex Getter 是 store 中定义的函数,可以从 store 中获取状态。使用 Getter 可以在组件中获取 store 状态,而不需要直接访问 store。由于 Getter 是响应式的,因此当 store 状态发生变化时,Getter 的值也会自动更新,从而触发组件中依赖 Getter 的计算方法重新计算。

示例代码:

// store getter
export const currentUser = state => {
  return state.users.current_user.id;
}
// component using getter
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters({
      currentUser: 'currentUser',
    }),
    notifications() {
      return Notification.query()
        .where('target_type', 'User')
        .where('target_id', this.currentUser)
        .orderBy('created_at', 'desc').get()
    },
  },
}

2. 手动调用计算方法

可以通过在 store 状态发生变化时手动调用计算方法来解决这个问题。例如,可以在 store 的 mutation 中手动调用依赖该 mutation 的计算方法。

示例代码:

// mutation that commits the new user ID
export const setUserId = (state, id) => {
  state.users.current_user.id = id;
  this.currentUser_id(); // manually call the computed method
}
// component using manual invocation
export default {
  computed: {
    notifications() {
      return Notification.query()
        .where('target_type', 'User')
        .where('target_id', this.currentUser_id)
        .orderBy('created_at', 'desc').get()
    },
    currentUser_id() {
      return this.$store.state.users.current_user.id
    }
  },
  watch: {
    currentUser_id() {
      this.currentUser_id(); // manually call the computed method
    }
  },
}

结论

通过使用 Vuex Getter 或手动调用计算方法,可以确保计算方法在 store 状态更改时得到及时更新。这将解决组件中计算方法不动态更新的问题,从而保证组件状态与 store 状态始终保持一致。

常见问题解答

1. 为什么会出现这个问题?

当 store 使用 async/await 时,异步操作会在事件循环的下一轮中执行,导致在计算方法执行时,store 状态尚未更新。

2. Getter 和手动调用计算方法有什么区别?

Getter 是一种自动更新计算方法,而手动调用计算方法需要在 store 状态发生变化时手动触发。

3. 哪种解决方案更好?

使用 Getter 是一种更方便、更优雅的解决方案,因为它可以自动处理计算方法的更新。但是,在某些情况下,手动调用计算方法也可能是必要的,例如当计算方法依赖于其他计算方法时。

4. 是否还有其他解决方法?

可以使用 Vuex Actions 来处理异步操作,并确保在状态更改后触发计算方法。

5. 如何避免这个问题在将来发生?

在 store 中使用一致的异步处理方法,并了解 async/await 的行为,可以帮助避免此问题在将来发生。