【问题标题】:How do I use Vue.set() properly?如何正确使用 Vue.set()?
【发布时间】:2019-05-22 16:55:48
【问题描述】:

我正在尝试在我的商店中创建一个响应式数组。

我目前尝试使用 :key 强制更新、$forceUpdate() 和 Vue.set()。我最初是在日历组件中获取和更新数据,但我将获取数据逻辑移动到存储中,希望以某种方式使其具有反应性。当前属性在规定的 v 日历日期上显示一个红点。据我所知,该数组正在填充与单个属性具有完全相同结构的对象,但它不是反应性的。

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    loading: true,
    odata: [],
    attributes: [{
      dates: new Date(),
      dot: 'red',
      customdata: {
        programEventsSystemrecordID: 1234
      }
    }]

  },
  mutations: {
    updateAtts (state) {
      let singleAtt = {}
      let index = 0

      state.odata.forEach((ticket) => {
        Vue.set(singleAtt, 'dot', 'red')
        Vue.set(singleAtt, 'dates', new Date(ticket.ProgramEventsStartdate))
        Vue.set(singleAtt, 'customData', {})

        singleAtt.customData = {
          programEventsSystemrecordID: ticket.ProgramEventsSystemrecordID
        }

        Vue.set(state.attributes, index, singleAtt)

        index++
      })
    },
    updateOdata (state, odata) {
      state.odata = odata
    },
    changeLoadingState (state, loading) {
      state.loading = loading
    }

  },
  actions: {
    loadData ({ commit }) {
      axios.get('https://blackbaud-odata-cal-bizcswpdjy.now.sh')
        .then((response) => {
          commit('updateOdata', response.data)
        })
        .catch((err) => {
          console.log(err)
        })
        .finally(() => {
          console.log(commit('updateAtts'))
          commit('changeLoadingState', false)
        })
    }

  }
})

我希望 vue 中填充的数组能够更新 DOM。没有错误消息。

【问题讨论】:

  • 你能为此做一个可验证的小提琴吗? Vuex store 默认应该是响应式的,不需要在状态上做Vue.set()
  • 在你刚刚创建的对象上使用 Vue.set(所以它不在状态,不响应)是没用的。只需使用 array.push({my:"obj"}),它就可以工作。目前您为数组设置了很多时间相同的对象。
  • @YomS。我会做一个小提琴。
  • @Slim 当我做state.odata.forEach((ticket) => { state.attributes.push({ date: new Date(ticket.ProgramEventsStartdate), dot: 'red', customData: { programEventsSystemrecordID: ticket.ProgramEventsSystemrecordID } }) 它仍然不起作用
  • 所以代码中还有其他问题,这与状态反应性无关,因为状态总是反应性的。

标签: vue.js vuex


【解决方案1】:

Vue.set 在你的情况下是没用的。在大多数情况下,它是无用的。

需要在最初没有的状态下添加新属性。

在这里,您只有一个从另一个构建的状态属性。

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        loading: true,
        odata: [],
        attributes: [{
            dates: new Date(),
            dot: 'red',
            customdata: {
                programEventsSystemrecordID: 1234
            }
        }]

    },
    mutations: {
        updateAtts (state) {
            state.attributes = state.odata.map(t=>({
                dot: 'red',
                dates: new Date(t.ProgramEventsStartdate),
                customData: {programEventsSystemrecordID: t.ProgramEventsSystemrecordID}
            }))
        },
        updateOdata (state, odata) {
            state.odata = odata
        },
        changeLoadingState (state, loading) {
            state.loading = loading
        }

    },
    actions: {
        loadData ({ commit }) {
            axios.get('https://blackbaud-odata-cal-bizcswpdjy.now.sh')
                .then((response) => {
                    commit('updateOdata', response.data)
                })
                .catch((err) => {
                    console.log(err)
                })
                .finally(() => {
                    console.log(commit('updateAtts'))
                    commit('changeLoadingState', false)
                })
        }

    }
})

【讨论】:

  • 所以为了清楚起见,即使这些对象实际上并不存在于数组中,它仍然应该是反应式的吗?想知道我是否需要以某种方式使用拼接? vuejs.org/v2/guide/list.html#Caveats
  • 不,当然,当您在 js 中使用 {} 创建对象时,它不是响应式的。一旦您在状态中的对象中影响它,它就会变得反应。是的,数组有一些破坏反应性的操作,你有很好的链接。永远不要做 arr[4] = "thing" 或 arr.length = 0。另外,永远不要创建属性,用所有属性准备你的状态(即使是 null)。但是是的,你可以做 state.foo = {bar:8} (如果你的状态最初有 foo:null)
  • 正如@Slim 上面所说,我的代码中还有其他问题。他的回答有助于理解 Vue 中的反应性。
猜你喜欢
  • 2019-05-18
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 2012-07-12
  • 2013-01-21
  • 2021-10-24
相关资源
最近更新 更多