【问题标题】:Vue computed property not responding to state changeVue 计算属性不响应状态变化
【发布时间】:2019-09-27 04:13:54
【问题描述】:

我无法弄清楚为什么在调用 fetch() 方法时,以下组件中的 details 计算属性没有更新:

<template>
  <div>
  {{ haveData }} //remains undefined
  </div>
</template>

<script>
export default {
  props: {
    group: {
      type: Object,
      required: true
    },
  },
  computed: {
    currentGroup() {
      return this.$store.getters['user/navbar_menu_app_current_group'](
        this.group.id
      )

      /*-- which is the following function 
        navbar_menu_app_current_group: state => item => {
        return state.menu.find(m => {
          return m.id == item
        })
        }
      */

      /*-- this function returns an object like so 
        {
          id: 1,
          label: 'kity cats',
        }
        ***details --> IS NOT DEFINED. If I add it to the current group as null, my problem goes away. However, this is a previous API call that does not set the `details` parameter.
      */
    },
    details() {
      let c = this.currentGroup.details
      console.log(c) // returns undefined, which makes sense, but it should be updated after this.fetch() is called
      return c
    },
    haveData() {
      return this.details != null
    }
  },
  methods: {
    async fetch() {
      await this.$store.dispatch(
        'user/navbar_menu_app_details_get',
        this.group.id
      )
      //This is setting the "details" part of the state on menu which is referred to in the computed properties above
      //Previous to this there is no state "this.group.details"
      //If I add a console log to the mutation the action calls, I get what is expected.
    }
  },
  created() {
    if (!this.haveData) {
      this.fetch()
    }
  }
}
</script>

如果我将数组项更改为包含details,它会起作用:

{
  id: 1,
  label: 'kity cats',
  details: null  // <-- added
}

不幸的是,数组是通过大型 API 调用创建的,添加 details 似乎没有必要,因为它可能永远不需要。

如何在不将 details:null 添加到默认状态的情况下使计算属性正常工作?

尝试 1:

// Vuex mutation
navbar_menu_app_details_set(state, vals) {
  let app = state.menu.find(item => {
    return item.id == vals[0] //-> The group id passing in the dispatch function 
  })

  //option 1 = doesn't work
  app = { app, details: vals[1] } //-> vals[1] = the details fetched from the action (dispatch)

  //option 2 = doesnt work
  app.details = vals[1]

  //option 3 = working but want to avoid using Vue.set()
  import Vue from 'vue' //Done outside the actual function
  Vue.set( app, 'details', vals[1])
},

尝试 2:

// Vuex action
navbar_menu_app_details_get(context, id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      context.commit('navbar_menu_app_details_set', [
        context.getters.navbar_menu_app_current(id), //-> the same as find function in the mutation above
        apps[id]
      ])
      resolve()
    }, 1000)
  })
}

// --> mutation doesn't work
navbar_menu_app_details_set(state, vals) {
  vals[0].details = vals[1]
},

【问题讨论】:

  • 如果细节不存在,你可能想阅读vuejs.org/v2/guide/reactivity.html,它不可能是反应性属性,所以不确定你想象它会如何反应。
  • https://vuex.vuejs.org/guide/mutations.html 我需要通过Vue.set( originalData, label, newData) 设置新属性,这意味着我需要在商店中导入vue - 这是模块化的并且使用Nuxt 有没有办法参考全局 vue,所以我不需要到处导入Vue
  • 根据您提供的链接“由于 Vuex 商店的状态是由 Vue 做出的反应,当我们改变状态时,观察状态的 Vue 组件将自动更新。这也意味着 Vuex 突变在使用普通 Vue 时会受到相同的反应性警告
  • 我按回车键快速 - 我可以将vue 导入每个商店模块吗?
  • 似乎没有必要,需要导入额外的数据,而且有点难看。但如果这就是我需要做的,那我会做的。我只是好奇是否有更清洁的方法来做到这一点。在突变中,我确实可以访问this._vm,但这与Vue.set() 不同

标签: vue.js vuejs2 vuex


【解决方案1】:

Vue 实例可通过 this._vm 从 Vuex 突变获得,您可以使用 vm.$set()(相当于 Vue.set())将 details 添加到菜单项:

navbar_menu_app_details_set(state, vals) {
  let app = state.menu.find(item => {
    return item.id == vals[0]
  })

  this._vm.$set(app, 'details', vals[1])
},

【讨论】:

    【解决方案2】:

    Vue 中的所有对象 都是反应式 并且被设计成只有当对象被重新分配,更改将被捕获并进行更改检测。

    这样,在你的情况下,以下应该没问题。

    app = { ...app, details: vals[1] }
    

    【讨论】:

      猜你喜欢
      • 2021-12-16
      • 2021-10-31
      • 1970-01-01
      • 2017-12-31
      • 2020-03-02
      • 2020-07-08
      • 2020-12-01
      • 2018-12-18
      • 2019-07-09
      相关资源
      最近更新 更多