2

我将 Vue 与 Vuex 一起使用。在一种情况下,我使用 Ajax 来获取表示值。在路上的某个地方,可能computed它不再是被动的。

在我的组件中:

props: [ 'x', 'y' ],
template: `
  <div class="presentation">
    {{ presentation }}
  </div>
`,
computed: {
  presentation() {
    return this.$store.getters.presentation({ x: this.x, y: this.y });
  }
}

Vuex商店:

const store = new Vuex.Store({
  state: {
    table: {
      data: []
    }
  },
...

Vuex 动作:

我用ajax调用一个url并返回一个promise。我也犯了一个突变。

actions: {
  save: (context) => {
    let uri = 'some/uri';
    let params = {};
    let value = 'A value';

    return axios
    .post(uri, params)
    .then((response) => {
      context.commit('setPresentation', value);
    })
    .catch((error) => {
      console.log('error');
    })
    .finally(() => {});
  },
},

Vuex 突变:

mutations: {
  setPresentation: (state, value) => {
    let pos = state.table.pos;
    state.table.data[pos.y][pos.x].presentation = value;
  },
}

Vuex 吸气剂:

getters: {
  presentation: (state) => (pos) => {
    return state.table.data[pos.y][pos.x].presentation;
  }
},

我已经确定了以下几点:

  • 我将table.data状态设置为默认值以使其具有反应性
  • 使用 getter 获取数据
  • 使用 ajax 调用的动作
  • 在操作中调用带有提交的突变

笔记:

  • ajax 调用需要在一个动作中而不是在创建中,因为我presentation要从多个组件中使用。
  • 我更喜欢不需要外部 Vue 插件的解决方案。

问题)

  • 我错过了什么?
  • 我怎样才能以最好的方式解决它?
4

3 回答 3

4

您需要使用Vue.set而不是state.table.data[pos.y][pos.x].presentation = value;

有关详细信息,请参阅https://vuejs.org/v2/guide/list.html#Caveats

尝试使用以下代码更新您的突变:

if (!state.table.data[pos.y]) {
  Vue.set(state.table.data, pos.y, [])
}
Vue.set(state.table.data[pos.y], pos.x, { presentation: value })

来自我的一句话,OP(原始海报):

为什么它第一次失败是因为我只设置了我已经拥有{ presentation: value }的最后一部分并设置了另一个 ajax 调用。Vue.setpos.ypos.x

为了让 Vue 充分了解我是否需要设置所有尚未设置为状态的更改,使用Vue.set. 所以我需要使用Vue.set来设置pos.ypos.x

另请参阅下面的另一个出色答案

当您直接设置具有索引的项目时,Vue 无法检测到对数组的更改

于 2019-08-09T06:35:34.503 回答
2

你的突变没问题;那里没有问题。只要 Vue 正在观察对象,presentation Vue 就会很好地检测到对象属性的分配。

在大多数情况下,Vue 会自动观察对象,但是您需要注意一些怪癖(尤其是数组)。

当您直接使用索引 ( docs )设置项目时,Vue 无法检测到对数组的更改。

我假设您正在以下列方式填充数组:

for (let y = 0; y < Y_MAX; y++) {
  // This is bad! Vue cannot detect this change
  state.table.data[y] = []

  for (let x = 0; x < X_MAX; x++) {
    // Same as above, Vue cannot detect this change. As a consequence,
    // the object you are assigning to the array will not be observed
    // by Vue! So if you were to mutate the presentation property
    // of this object, Vue won't know about it.
    state.table.data[y][x] = { presentation: '...' }
  }
}

因此,要解决您的问题,您只需要确保您没有以下列方式改变数组:

array[index] = whatever

你需要这样做:

Vue.set(array, index, whatever)

或者,您可以先构建数组,然后将其分配给state.table.data last;Vue 将检测分配,然后递归地观察数组和其中包含的所有内容。

const data = []

for (let y = 0; y < Y_MAX; y++) {
  data[y] = []

  for (let x = 0; x < X_MAX; x++) {
    data[y][x] = { presentation: '...' }
  }
}

// After this assignment, data (and all objects contained within it)
// will be observable
state.table.data = data
于 2019-08-09T12:45:05.167 回答
0

看起来你的道具是一个数组。您确定 this.x 和 this.y 在您的演示方法中返回正确的值吗?

于 2019-08-09T07:09:39.457 回答