显示在v-for列表中的元素:VueJS

huangapple go评论91阅读模式
英文:

show element in v-for list: VueJS

问题

我有一个v-for循环,用于显示所有的项目,每个项目都有一个面板(用于修改和删除),但当我点击此按钮来显示我的面板时,它会出现在所有的项目上。如何避免这种情况?当我点击修改按钮时,修改项目的输入框也会出现在每个元素上。

这是我的代码:

<div v-for="(comment, index) in comments" :list="index" :key="comment">
   <div v-on:click="show = !show">
      <div v-if="show">
         <button @click="edit(comment), active = !active, inactive = !inactive">
            修改
         </button>
         <button @click="deleteComment(comment)">
            删除
         </button>
      </div>
   </div>
   <div>
      <p :class="{ active: active }">
        {{ comment.content }}
      </p>
      <input :class="{ inactive: inactive }" type="text" v-model="comment.content" @keyup.enter="doneEdit">
   </div>
</div>

以及方法和数据:

data() {
  return {
    show: false,
    editing: null,
    active: true,
    inactive: true
  }
},

methods: {
   edit(comment) {
     this.editing = comment
     this.oldComment = comment.content
   },

   doneEdit() {
     this.editing = null
     this.active = true
     this.inactive = true
   }
}
英文:

I have a v-for which display all my items and I have a panel for each items (to modify and delete) but when I click on this button to display my panel, it appears on all of my items. How can I avoid that ? This is the same thing when I click on modify button, the input to modify my item appears on each element.

There is my code :

&lt;div v-for=&quot;(comment, index) in comments&quot; :list=&quot;index&quot; :key=&quot;comment&quot;&gt;
   &lt;div v-on:click=&quot;show = !show&quot;&gt;
      &lt;div v-if=&quot;show&quot;&gt;
         &lt;button @click=&quot;edit(comment), active = !active, inactive = !inactive&quot;&gt;
            Modify
         &lt;/button&gt;
         &lt;button @click=&quot;deleteComment(comment)&quot;&gt;
            Delete
         &lt;/button&gt;
      &lt;/div&gt;
   &lt;/div&gt;
   &lt;div&gt;
      &lt;p :class=&quot;{ active: active }&quot;&gt;
        {{ comment.content }}
      &lt;/p&gt;
      &lt;input :class=&quot;{ inactive: inactive }&quot; type=&quot;text&quot; v-model=&quot;comment.content&quot; @keyup.enter=&quot;doneEdit&quot;&gt;
   &lt;/div&gt;
&lt;/div&gt;

And the methods & data :

data() {
  return {
    show: false,
    editing: null,
    active: true,
    inactive: true
  }
},

methods: {
   edit(comment) {
     this.editing = comment
     this.oldComment = comment.content
   },

   doneEdit() {
     this.editing = null
     this.active = true
     this.inactive = true
   }
}

</details>


# 答案1
**得分**: 4

您对所有项目都具有相同的“显示”,“编辑”,“活动”,“非活动”状态。因此,如果您更改一个项目的某个数据属性,它将影响所有项目。
有很多方法可以实现您想要的效果。

最简单的方法是通过索引来管理您的数据。
例如:

    <div v-on:click="showIndex = index">
      <div v-if="showIndex === index">
      ...
    data () {
      return {
        showIndex: null
      ...

这种方法的主要问题是 - 您一次只能显示/编辑一个项目。
如果您需要更复杂的逻辑并且希望同时管理多个项目,我建议为您的项目创建一个单独的组件,每个组件都具有自己的状态(例如“显示”,“编辑”等)。

<details>
<summary>英文:</summary>

You have the same `show`, `editing`, `active`, `inactive` state for all items. So if you change some data property for one item it changed for all. 
There are a lot of ways to achieve what you want.

The easiest is to manage your data by index.
For example: 

    &lt;div v-on:click=&quot;showIndex = index&quot;&gt;
      &lt;div v-if=&quot;showIndex === index&quot;&gt;
      ...
    data () {
      return {
        showIndex: null
      ...

The main problem with this approach - you can show/edit only one item at the time. 
If you need more complicated logic and whant to manage more then one item at the time I suggest to create a separate component for your items and each will have own state (`show`, `editing` etc.)


</details>



# 答案2
**得分**: 3

@NaN的方法适用于只允许同时打开一个元素的情况。如果你想要同时打开多个元素的可能性,你需要跟踪每个单独的元素。目前,你只是基于`show`来操作,这个值对于所有元素只能是`true/false`。

所以这是你需要做的:

将`show`从布尔值改为数组
```js
data() {
  return {
    show: [],
    editing: null,
    active: true,
    inactive: true,
  }
},
```

然后你可以跟踪哪个元素应该有面板或者不应该有面板:

```html
<div v-on:click="toggleActive(index)">
```

然后在方法中:

```js
methods: {
   toggleActive(index) {
      if (this.show.includes(index)) {
        this.show = this.show.filter(entry => entry !== index);
        return; 
      }
      
      this.show.push(index);
   }
}
```

最后你的`v-if`变成了:

```html
<div v-if="show.includes(index)">
```

<details>
<summary>英文:</summary>

@NaN&#39;s approach works if you want to only have one open at a time. If you want to have the possibility of having multiple open at the same time you would need to keep track of each individual element. Right now you are only basing it on `show`. Which can only be `true/false` for all elements at the same time.

So this is what you need to do:

Change `show` from a boolean to an array
```
data() {
  return {
    show: [],
    editing: null,
    active: true,
    inactive: true,
    
  }
},
```

Then you can keep track of which element should have the panel or not:

```html
&lt;div v-on:click=&quot;toggleActive(index)&quot;&gt;
```

And the method:

```js
methods: {
   toggleActive(index) {
      if (this.show.includes(index)) {
        this.show = this.show.filter(entry =&gt; entry !== index);
        
        return; 
      }
      
      this.show.push(index);
   }
}
```
and finally your `v-if` becomes:

```html
&lt;div v-if=&quot;show.includes(index)&quot;&gt;
```

</details>



huangapple
  • 本文由 发表于 2020年1月4日 01:12:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/59582624.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定