简体   繁体   English

VueJS在v-for中只选择一个元素

[英]VueJS Select only one element in a v-for

I'm using Vue v2我正在使用 Vue v2

I'm trying to change only the properties of the selected element.我正在尝试仅更改所选元素的属性。 See, when the response is marked after the click, it should change to a red color with a text that says 'Unmark'.看,当点击后响应被标记时,它应该变为红色,并带有“取消标记”的文本。 And vice versa: if the button is clicked again (which now would say 'Unmark'), it should change to a green color and the text would be 'Mark'.反之亦然:如果再次单击按钮(现在会显示“取消标记”),它应该变为绿色,文本将是“标记”。 Alas, it works.... Nevertheless, my code applies the change to every element inside the v-for;唉,它有效......不过,我的代码将更改应用于 v-for 中的每个元素; I only want that to happen to the selected element.我只希望所选元素发生这种情况。

I've thought about using a Component to check if somethings changes, but first I'd like to see if there's a solutions for this.我想过使用组件来检查是否有变化,但首先我想看看是否有解决方案。 ANy help will be appreciated任何帮助将不胜感激

Here's my code:这是我的代码:

<div class="search-results">
                <div class="activity-box-w" v-for="user in users">
                    <div class="box">
                      <div class="avatar" :style="{ 'background-image': 'url(' + user.customer.profile_picture + ')' }">
                      </div>
                      <div class="info">
                        <div class="role">
                          @{{ '@' + user.username }}
                        </div>
                        <div>
                            <div>
                                <p class="title">@{{ user.customer.name }} 
                                @{{user.customer.lastname}}
                                </p>
                            </div>

                        </div>
                      </div>
                      <div class="time">
                        <input type="button" class="btn btn-sm btn-primary" v-on:click.prevent="markUser(user)" v-model="text" 
                        v-bind:class="[{'green-border':notMarked}, {'red-border':marked}]" v-cloak v-if="!action"
                        :disabled="action"></input>
                    </div>
                </div>
            </div>

Now for the script:现在脚本:

new Vue({
  el: '#engage-panel',
  data: {
    users: [],
    mark: {'id' : '', 'marks' : ''},
    text: 'Mark', //Migth change to Unmark later on
    action: false,
    marked: null,
    notMarked: null,
  }, 
    methods:
{   
markUser: function(user){

      this.mark.id = user.id;
      this.action= true;

      Vue.http.headers.common['X-CSRF-TOKEN'] = $('meta[name="csrf-token"]').attr('content');
      this.$http.put('/mark/user', this.mark).then(response => {

                  if(response.body === "marked")
                  {
                      this.mark.marks="true";
                      this.text = 'Unmark';
                      this.marked= true;
                      this.notMarked= false;
                      this.action= false;

                  }else{
                      this.mark.marks="false";                  
                      this.text = 'Mark';
                      this.marked= false;
                      this.notMarked= true;
                      this.action= false;
                  }

                }).catch(e => {

                    this.action= false;
                });
    }

}

The issue my code applies the change to every element you met is caused by every user in v-for="user in users" uses one same object to indicates it is marked or not. my code applies the change to every element您遇到的my code applies the change to every element的问题是由v-for="user in users"的每个用户使用同一个对象来指示它是否被标记引起的。

If your users data has one property like status to save current status (like unmark, mark etc), it is very simple, just change to next status when click mark button.如果你的users数据有一个属性,比如状态来保存当前状态(如取消标记,标记等),这很简单,只需在单击标记按钮时更改为下一个状态。

If your users data doesn't have that property, you need to create one dictionary, then save the users already clicked as key, the status for the user will be the value.如果您的users数据没有该属性,则需要创建一个字典,然后将已单击的用户保存为键,该用户的状态将是该值。

Below is one demo:下面是一个演示:

 app = new Vue({ el: "#app", data: { users1: [{'name':'abc', 'status':'none'}, {'name':'xyz', 'status':'none'}], users2: [{'name':'abc'}, {'name':'xyz'}], selectedUsers: {} }, methods: { getNextStatusBaseOnRoute: function (status) { if(status ==='marked') return 'marked' let routes = {'none':'unmark', 'unmark':'marked'} return routes[status] }, markUser1: function (item) { item.status = this.getNextStatusBaseOnRoute(item.status) }, markUser2: function (item) { let status = item.name in this.selectedUsers ? this.selectedUsers[item.name] : 'none' // remember to use vue.$set when adding new property to one object this.$set(this.selectedUsers, item.name, this.getNextStatusBaseOnRoute(status)) } } })
 .marked { background-color:green; } .unmark { background-color:yellow; }
 <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script> <div id="app"> <h2>Case 1: </h2> <div v-for="(item, index1) in users1" :key="'1'+index1"> <span>{{item.name}}:</span><span :class="[item.status]">{{item.status}}</span><button @click="markUser1(item)">Mark</button> </div> <h2>Case 2: </h2> <div v-for="(item, index2) in users2" :key="'2'+index2"> <span>{{item.name}}:</span><span :class="[item.name in selectedUsers ? selectedUsers[item.name] : 'none']">{{item.name in selectedUsers ? selectedUsers[item.name] : 'none'}}</span><button @click="markUser2(item)">Mark</button> </div> </div>

You can use $event.target on click if you just need to toggle css class.如果您只需要切换 css 类,您可以在单击时使用$event.target fiddle here在这里摆弄

But it's true that it's easier if a user has a status like marked = true/false for example, you just need to bind class like :但是确实,如果用户具有marked = true/false类的状态,则确实会更容易,例如,您只需要绑定如下类:

<input :class="{ 'green-border': user.marked, 'red-border': !user.marked }">

For Vue3, you can also store the index of the selected element对于Vue3,还可以存储被选元素的索引

<ul role="list" class="">
  <li class="relative" v-for="(image, index) of images" :class="selectedImage == index? 'border-indigo-500 border-2': 'border-transparent'" >
    <div @click="selectedImage = index" class="">
      <img :src="image" alt="" class="object-cover pointer-events-none group-hover:opacity-75">
    </div>
  </li>
</ul>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM