【问题标题】:How can I modify a value in a array with a click method ? [VueJS]如何使用 click 方法修改数组中的值? [VueJS]
【发布时间】:2019-02-07 17:33:41
【问题描述】:

我今天刚开始使用 vuejs。我得到了 vue “example1”,其中包含一个变量“items”作为数据。这个变量包含一个数组“deck”。该数组包含多个角色统计信息(团队、武器、位置...)。

如果您有任何解决方案或任何可以找到我的答案的方向,我不知道如何解决这个问题。

我想点击字符,修改由“x”绑定的gridColumn位置。它们显示在 9*12 的网格上。

非常感谢。

html, body {
	margin: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}
#board {
    display: grid;
    grid-template-columns: repeat(12, 80px);
    grid-template-rows: repeat(9, 80px);
    grid-gap: 10px;
}
#board .card {
    background-color: pink;
    border: 2px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<section id="board">
        <div class="card" v-for="item in items" v-bind:style="{backgroundColor:item.bg,gridColumn:item.x,gridRow:item.y}" v-on:click="move">
            {{ item.clan }}
            <br>
            {{ item.arme }}
            <br>
            {{ item.force }}
        </div>
    </section>
   <script>
        var deck = [
                    //natif
                    {
                        clan: 'natif',
                        arme:'filet',
                        force: 1,
                        bg: 'green',
                        x: 2,
                        y: 6
                    },
                    {
                        clan: 'natif',
                        arme:'filet',
                        force: 2,
                        bg: 'green',
                        x: 3,
                        y: 6
                    }
                    //etc
                ];
        var example1 = new Vue({
            el: '#board',
            data: {
                items: deck
            },
            methods: {
                move: function () {
                    // increase "x" value of the clicked item.
                }
            }
        });
    </script>

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    你可以传递被点击项的索引,并通过引用索引在函数内部进行修改。

    html, body {
    	margin: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
    }
    #board {
        display: grid;
        grid-template-columns: repeat(12, 80px);
        grid-template-rows: repeat(9, 80px);
        grid-gap: 10px;
    }
    #board .card {
        background-color: pink;
        border: 2px solid black;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <section id="board">
             <div class="card" v-for="(item,index) in items" v-bind:style="{backgroundColor:item.bg,gridColumn:item.x,gridRow:item.y}" v-on:click="move(index)">
              {{ item.clan }}
                <br>
                {{ item.arme }}
                <br>
                {{ item.force }}
            </div>
        </section>
       <script>
            var deck = [
                        //natif
                        {
                            clan: 'natif',
                            arme:'filet',
                            force: 1,
                            bg: 'green',
                            x: 2,
                            y: 6
                        },
                        {
                            clan: 'natif',
                            arme:'filet',
                            force: 2,
                            bg: 'green',
                            x: 3,
                            y: 6
                        }
                        //etc
                    ];
            var example1 = new Vue({
                el: '#board',
                data: {
                    items: deck
                },
                methods: {
                move: function (i) {
                    this.items = this.items.map((item,indx) => {
                      if(indx === i)
                          return ({...item,x: item.x + 1});
                      return item;
                    }) //modify logic accordingly
                
            }
                }
            });
        </script>

    【讨论】:

    • 完成。我不能更早地导致计时器。
    • 这不是我们在 Vue 中的做法,您正在以错误的方式改变数组!
    • @saibbyweb 你有更好的选择吗?
    • 是的!等等,让我发布它。
    • @saibbyweb 实际上,改变 props 被认为是一种反模式,但是你可以改变数据,因为 Object 访问器都被 VUE 覆盖了。所以,这可能不是最好的方式,但也不是错误的方式
    【解决方案2】:

    这就是你按照OFFICIAL VUE.JS DOCUMENTATION做的方法

    [用Vue.set方法改变数组]:

    var deck = [
      //natif
      {
        clan: 'natif',
        arme: 'filet',
        force: 1,
        bg: 'green',
        x: 2,
        y: 6
      },
      {
        clan: 'natif',
        arme: 'filet',
        force: 2,
        bg: 'green',
        x: 3,
        y: 6
      }
      //etc
    ];
    var example1 = new Vue({
      el: '#board',
      data: {
        items: deck
      },
      methods: {
        move: function(index) {
    
          /* creating a REFERENCE of the clicked item's object */
          let modifiedObject = this.items[index];
    
          /*  increaseing "x" value of temporary REFERENCE */
          modifiedObject.x++;
    
          /* Mutating the items array WITHOUT LOSING    REACTIVITY by replacing the existing object with local modified object */
          Vue.set(this.items, index, modifiedObject);
        }
      }
    });
    html,
    body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    #board {
      border: 1px solid black;
      display: grid;
      grid-template-columns: repeat(12, 40px);
      grid-template-rows: repeat(9, 40px);
      grid-gap: 10px;
    }
    
    #board .card {
      background-color: pink;
      border: 2px solid black;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <section id="board">
      <div class="card" v-for="(item,index) in items" v-bind:style="{backgroundColor:item.bg,gridColumn:item.x,gridRow:item.y}" v-on:click="move(index)">
        {{ item.clan }}
        <br> {{ item.arme }}
        <br> {{ item.force }}
      </div>
    </section>

    【讨论】:

    • /* creating a copy of the clicked item's object */ let modifiedObject = this.items[index]; 不会创建副本,因为 this.items[index] 是一个对象并且只传递了一个引用
    • 我的错,只是为了让新手保持简单。
    • 好吧,实际上,它也等同于“错误”的做事方式,因为你正在变异。 Vue.set( 在添加新密钥时使用。 vuejs.org/v2/guide/reactivity.html
    • 我唯一的目标是让它保持被动。您最初的回答完全违背了使用 vue 的目的,这就是我指出的原因。
    猜你喜欢
    • 2021-01-12
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2023-02-20
    • 2021-11-23
    相关资源
    最近更新 更多