简体   繁体   English

Vue 在循环中单击的项目上添加类并从其他项目中删除

[英]Vue add class on clicked item in loop and remove from other items

I have a loop where I loop over an Array.我有一个循环,我循环遍历一个数组。

for each item in this array I render a new component.对于这个数组中的每个项目,我渲染一个新组件。 Now when a user clicks on a certain component I only want to add a class to that component to highlight it and remove it from others that have it.现在,当用户单击某个组件时,我只想向该组件添加一个类以突出显示它并将其从其他拥有它的组件中删除。 Think of it as a menu active item.将其视为菜单活​​动项。

<step-icon
  v-for="(step, currentStep) in steps"
/>

data() {
  return {
    steps: [{foo: 'bar'}, {foo2: 'bar2'}]
  }
}

my step-icon.vue:我的 step-icon.vue:

<template>
  <div :class="{'selected': selected}" @click="clickStep()">
    hello
  </div>
</template>

data() {
  return {
    selected: false
  }
},
methods: {
  clickStep() {
      this.selected = true;
  }
}

This works only 1 way, I can only add the selected class but never remove it.这只有一种方式,我只能添加选定的类,但永远不会删除它。

I created a simple example illustrating your use case since you didn't provided enough detail to go with.我创建了一个简单的例子来说明你的用例,因为你没有提供足够的细节来说明。 Below you can find the items selected and unselected.您可以在下方找到选中和未选中的项目。 Firstly, we added a key isSelected and set it to false as default.首先,我们添加了一个键isSelected并将其设置为 false 作为默认值。 This will act as a status for all items.这将作为所有项目的状态。

steps: [
  {key:"0", tec:"foo", isSelected:false},
  {key:"1", tec:"bar", isSelected:false},
  {key:"2", tec:"foo2", isSelected:false},
  {key:"3", tec:"bar2", isSelected:false},
]

Next, we looped over the array and displayed all the items.接下来,我们遍历数组并显示所有项目。

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

Here you can se we have set our status property isSelected on v-bind directive which will add or remove the class based on the value of isSelected .在这里你可以看到我们在 v-bind 指令上设置了我们的状态属性isSelected ,它将根据isSelected的值添加或删除类。

Next, once the item is clicked we will trigger select method.接下来,一旦项目被点击,我们将触发select方法。

  methods: {
    select(key) {
      for (let i = 0; i < this.steps.length; i++) {
        if (this.steps[i].key !== key) {
          this.steps[i].isSelected = false
        }
      }

      this.toggleSelection(key)
    },
    toggleSelection(key) {
      const stepsItem = this.steps.find(item => item.key === key)
      if (stepsItem) {
        stepsItem.isSelected = !stepsItem.isSelected
      }
    }
  }

The select method will firstly unselect all those except the one which is selected and then call toggleSelection which will set the selected Item to true or false. select 方法将首先取消选择除已选择的以外的所有项目,然后调用toggleSelection将所选项目设置为 true 或 false。

Complete Code:完整代码:

 new Vue({ el: '#app', data: { steps: [ {key:"0", tec:"foo", isSelected:false}, {key:"1", tec:"bar", isSelected:false}, {key:"2", tec:"foo2", isSelected:false}, {key:"3", tec:"bar2", isSelected:false}, ] }, methods: { select(key) { for (let i = 0; i < this.steps.length; i++) { if (this.steps[i].key !== key) { this.steps[i].isSelected = false } } this.toggleSelection(key) }, toggleSelection(key) { const stepsItem = this.steps.find(item => item.key === key) if (stepsItem) { stepsItem.isSelected = !stepsItem.isSelected } } } })
 .selected { background: grey; } .notselected { background:transparent; }
 <script src="https://unpkg.com/vue@2.6.10"></script> <div id="app"> <ul> <li v-for="l in steps" id="l.key" @click="select(l.key, l.isSelected)" v-bind:class="{ selected : l.isSelected, notselected : !l.isSelected }" > {{ l.tec }} </li> <ul> </div>

You can keep all the step state in the parent component.您可以将所有step状态保留在父组件中。

Now the parent component can listen for toggle_selected event from the nested one, and call toggle_selected(step) with the current step as a param.现在父组件可以从嵌套的事件中监听toggle_selected事件,并以当前步骤作为参数调用toggle_selected(step)

Toggle_selected method should deselect all steps except the current one, and for the current one just toggle the selected prop. Toggle_selected方法应该取消选择除当前步骤之外的所有步骤,并且对于当前步骤只需切换selected道具。

If You would like to modify more props of the step in the nested component You could use .sync modifier ( :step.sync="step" ) and then this.@emit('update:step', newStepState) in the nested component.如果您想修改嵌套组件中步骤的更多道具,您可以在嵌套组件中使用.sync修饰符( :step.sync="step" ),然后使用this.@emit('update:step', newStepState) .

I've also made a snippet (my first).我还做了一个片段(我的第一个)。 In this example I omitted clickStep and just put @click="$emit('toggle_selected') in the step-icon component.在这个例子中,我省略了clickStep ,只是把@click="$emit('toggle_selected')放在step-icon组件中。

 new Vue({ el: '#app', // for this example only defined component here components: { 'step-icon': { props: { step: Object } } }, data: { steps: [ { name: 'Alfa', selected: false}, { name: 'Beta', selected: false}, { name: 'Gamma', selected: false}, ] }, methods: { toggle_selected(step) { this.steps.filter(s => s != step).forEach(s => s.selected = false); step.selected = true; } } })
 #app { padding: 2rem; font-family: sans-serif; } .step-icon { border: 1px solid #ddd; margin-bottom: -1px; padding: 0.25rem 0.5rem; cursor: pointer; } .step-icon.selected { background: #07c; color: #fff; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <!-- Ive used inline-template for this example only --> <div id="app"> <step-icon v-for="(step, currentStep) in steps" :key="currentStep" :step.sync="step" @toggle_selected="toggle_selected(step)" inline-template> <div class="step-icon" :class="{selected: step.selected}" @click="$emit('toggle_selected')"> {{ step.name }} </div> </step-icon> </div>

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

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