select/deselect v-for 中的单个元素

select/deselect single element in v-for

我正在尝试使用 v-for 创建一个选项列表,您一次只能在其中选择一个选项。效果很好,但我无法取消选择该选项。

<div id="main">
  <ul>
    <li 
        v-for="l in list" 
        id="l.key"
        @click="selectone(l.key, l.isSelected)"
        v-bind:class="{ selected : l.isSelected, notselected : !l.isSelected }"
        > {{ l.tec }} </li>
   <ul>
</div>

JS

new Vue({
  el:"#main",
  data: {
    list: [
      {key:"0", tec:"html", isSelected:false},
      {key:"1", tec:"css", isSelected:false},
      {key:"2", tec:"JS", isSelected:false},
      {key:"3", tec:"Git", isSelected:false},
      {key:"4", tec:"NodeJS", isSelected:false},
      {key:"5", tec:"Postgres", isSelected:false}
    ]
  },
  methods: {
    selectone: function(k, o) {
      for( i = 0; i < this.list.length; i ++ ) {
        if(this.list[i].isSelected == true ) {
          this.list[i].isSelected = false
        }
      }
      this.list[k].isSelected = !this.list[k].isSelected;
    }
  }
})

CSS

.selected {
    background:lightpink;
}
.notselected {
    background:lightblue;
}

我的循环不应该在每次单击元素时停用所有选项吗?

selectone() 中,您为 所有 列表项设置 isSelected=false,然后 尝试 切换所选列表项的 isSelected,它之前刚刚设置为 false(即,"toggle" 将始终为所选项目设置 isSelected=true)。

循环应该排除所选项目的键:

selectone(key) {
  for (let i = 0; i < this.list.length; i++) {
    if (this.list[i].key !== key) {
       this.list[i].isSelected = false
    }
  }

  // this.toggleSelection(key)
}

但是切换代码本身需要 bug-fix 才能正确查找列表项。 selectone() 的第一个参数是列表项的 key 属性。为了从 list 数组中按键获取项目,您必须搜索 list,例如,使用 Array.prototype.find():

toggleSelection(key) {
  const listItem = this.list.find(item => item.key === key)
  if (listItem) {
    listItem.isSelected = !listItem.isSelected
  }
}

new Vue({
  el: '#app',
  data: {
    list: [
      {key:"0", tec:"html", isSelected:false},
      {key:"1", tec:"css", isSelected:false},
      {key:"2", tec:"JS", isSelected:false},
      {key:"3", tec:"Git", isSelected:false},
      {key:"4", tec:"NodeJS", isSelected:false},
      {key:"5", tec:"Postgres", isSelected:false}
    ]
  },
  methods: {
    selectone(key) {
      for (let i = 0; i < this.list.length; i++) {
        if (this.list[i].key !== key) {
          this.list[i].isSelected = false
        }
      }

      this.toggleSelection(key)
    },
    toggleSelection(key) {
      const listItem = this.list.find(item => item.key === key)
      if (listItem) {
        listItem.isSelected = !listItem.isSelected
      }
    }
  }
})
.selected {
  background:lightpink;
}
.notselected {
  background:lightblue;
}
<script src="https://unpkg.com/vue@2.6.10"></script>

<div id="app">
  <ul>
    <li 
        v-for="l in list" 
        id="l.key"
        @click="selectone(l.key, l.isSelected)"
        v-bind:class="{ selected : l.isSelected, notselected : !l.isSelected }"
        > {{ l.tec }} </li>
   <ul>
</div>

或者,您可以跟踪所选索引,将其设置在项目的 click-处理程序中,并根据与所选索引匹配的项目索引设置 class 绑定:

// template
<li 
  v-for="(l, index) in list" 
  id="l.key"
  @click="selectedIndex = index"
  v-bind:class="{ selected: index === selectedIndex, notselected: index !== selectedIndex }"
  > {{ l.tec }} </li>

// script
export default {
  data() {
    return {
      selectedIndex: -1,
      ...
    }
  }
}

new Vue({
  el: '#app',
  data: {
    selectedIndex: -1,
    list: [
      {key:"0", tec:"html", isSelected:false},
      {key:"1", tec:"css", isSelected:false},
      {key:"2", tec:"JS", isSelected:false},
      {key:"3", tec:"Git", isSelected:false},
      {key:"4", tec:"NodeJS", isSelected:false},
      {key:"5", tec:"Postgres", isSelected:false}
    ]
  }
})
.selected {
  background:lightpink;
}
.notselected {
  background:lightblue;
}
<script src="https://unpkg.com/vue@2.6.10"></script>

<div id="app">
  <ul>
    <li 
        v-for="(l, index) in list" 
        id="l.key"
        @click="selectedIndex = index"
        v-bind:class="{ selected : index === selectedIndex, notselected : index !== selectedIndex }"
        > {{ l.tec }} </li>
   <ul>
</div>

你的关闭。试试这个:(未经测试)

<div id="main">
  <ul>
    <li 
        v-for="(l,index) in list" 
        id="l.key"
        @click="selectone(l, index)"
        v-bind:class="{ selected : l.isSelected, notselected : !l.isSelected }"
        > {{ l.tec }} </li>
   <ul>
</div>

JS

new Vue({
  el:"#main",
  data: {
    list: [
      {key:"0", tec:"html", isSelected:false},
      {key:"1", tec:"css", isSelected:false},
      {key:"2", tec:"JS", isSelected:false},
      {key:"3", tec:"Git", isSelected:false},
      {key:"4", tec:"NodeJS", isSelected:false},
      {key:"5", tec:"Postgres", isSelected:false}
    ]
  },
  methods: {
    selectone:function(l, index){

      for( i = 0; i < this.list.length; i ++ ) {
        this.list[i].isSelected = false
        }
      l.isSelected = true;
      }
    }
  }
})

解释一下你在函数中没有使用变量 k。那应该是整个对象而不是索引