直接在模板中使用/修改Vuex状态

Chr*_*zzz 5 mutation vue.js vuex

我想我对Vue + Vuex有误解。

我有一个 Vuex 状态,其中包含一个列表过滤器。列表中的每个过滤器项目都可以标记为已选择。但是 - Vuex 状态只能在单击应用按钮时通过修改器进行修改,以便其他组件可以对更改做出反应。

例如,列表将根据所选过滤器重新加载数据。当状态更新时,组件也应该更新。

我创建了一个CodePen:

https://codepen.io/anon/pen/OzEJWP?editors=1010

https://jsfiddle.net/rxqu7ame/

Vue.component('filter-item', {
    template: ` <div>
            <!--{{item.color}} ({{item.selected}}) <button @click="item.selected = !item.selected">toggle</button>-->
            {{item.color}} ({{isSelected}}) <button @click="isSelected = !isSelected">toggle</button>
          </div>`,
    data: function () {
        return {
            isSelected: this.item.selected
        }
    },
    computed: {
        /*isSelected : function(){
          return this.item.selected;
        }*/
    },

    props: ['item']
});  
Run Code Online (Sandbox Code Playgroud)

我遇到了不同的问题:

  1. selected当我直接在模板内切换属性时filter-item,Vuex 状态也会更新(我不想要)。

  2. 因此,我尝试使用状态初始化数据属性(组件的本地属性),这样只有数据变量isSelected会被更新。当我按下“应用”按钮时,Vuex 状态将被更新(稍后我将使用突变)。到目前为止,一切都很好。但现在,isSelected当状态发生变化时,该属性不会自动更新。

  3. 如果我使用计算属性,isSelected则无法在单击事件中更改(因为它是只读的)。

实现我想要的场景的正确方法是什么?

Eri*_*uan 0

更新的代码笔:https://codepen.io/guanzo/pen/xpzrMm ?editors=0010

我以前遇到过这种情况,发现最简单的方法是在商店中的“实际”变量旁边添加一个“临时”变量。“实际”变量是selected,“临时”变量是tempSelected“。tempSelected当用户切换颜色时将更新,并且selected当您“申请商店”时将更新。

这是默认商店状态的样子

filter: [
      {
        color: 'red',
        selected: false,
        tempSelected: false,
      },
      {
        color: 'green',
        selected: false,
        tempSelected: false,
      }      
    ]
Run Code Online (Sandbox Code Playgroud)

以下是如何通过突变切换单一颜色。您不应该通过引用直接更新存储,而应始终通过突变来完成。如果您对计算的 get/set 语法感到困惑,请查看此处: https: //v2.vuejs.org/v2/guide/compulated.html#Compulated-Setter

Vue.component('filter-item', {
  template: ` <div>
                {{item.color}} ({{item.tempSelected}}) 
<button @click="isSelected = !isSelected">toggle</button>
              </div>`,
  computed: {
     isSelected:{
       get(){
         var filter = this.$store.state.filter.find(filter=>filter.color === this.item.color)
         return filter.tempSelected
       },
       set(value){
         this.$store.commit('updateSelected',{
           color: this.item.color,
           selected: value
         })
       }
     }
  },
Run Code Online (Sandbox Code Playgroud)

这是更新单一颜色的商店突变。

updateSelected(state,payload){
  var filter = state.filter.find(filter=>filter.color===payload.color)
  filter.tempSelected = payload.selected
}
Run Code Online (Sandbox Code Playgroud)

现在您有了存储用户输入的临时变量。要“应用于存储”,您只需将实际变量的值设置为临时变量的值

updateFilters(state){
      state.updates++;
      state.filter.forEach(filter=>{
          filter.selected = filter.tempSelected
      })
    },
Run Code Online (Sandbox Code Playgroud)

要切换所有值,只需翻转当前selected值即可。但请务必保持tempSelected变量同步。

toggleFilters(state){
      state.updates++;
      state.filter.forEach(filter=>{
          filter.selected = !filter.selected
          filter.tempSelected = filter.selected
      })
    },
Run Code Online (Sandbox Code Playgroud)

现在实现“取消更改”功能很简单。如果用户希望撤消所有更改,您可以设置tempSelected为 的值selected,有效地将状态恢复到最后一个已知值。