web-dev-qa-db-ja.com

VueJS v-if = array [index]が機能していません

マウスを画像の上に置くとテキストボックスが表示されるコンポーネントを作成したいと思いました。

以下はHTMLテンプレートです。

<section class="item-container" v-for="(item, index) in items">
  <div class="image-box" @mouseenter="changeStatus(index)">
    <img class="image" src="item.link" alt>
  </div>
  <div class="text-box" @mouseleave="changeStatus(index)" v-if="show[index]">
    <h4>{{ item.name }}</h4>
    <p>{{ item.content }}</p>
  </div>
</section>

そして以下はapp.jsです

new Vue({
  el: '#app',
  data: {
    show: [false, false, false],
    items: [
      {
        name: 'Author 1',
        content: 'Content 1'
      },
      {
        name: 'Author 2',
        content: 'Content 2'
      },
      {
        name: 'Author 3',
        content: 'Content 3'
      }
    ]
  },
  methods: {
    changeStatus: function(index) {
      this.show[index] = !this.show[index];
      console.log(this.show); 
      console.log(this.show[index]);  // console gets it as expected
    }
  }
});

上記のコードを実行すると、showプロパティが変更されたことがわかります。ただし、v-ifは更新されません。 v-ifにarray [index]を使用できないのですか、それとも他の理由がありますか?

15
Jiseung Roh

問題は_v-if_に関するものではなく、Vueが配列要素の変更を直接検出できないためです。これはJavaScriptの制限の1つです。

したがって、Vueは、_Vue.set_のような、このためのいくつかのヘルパー関数を提供します

これを変更_this.show[index] = !this.show[index]_

Vue.set(this.show, index, !this.show[index])

その後、動作するはずです。

_Vue.set_が唯一の解決策ではありません。知りたい場合に備えて、これを実現する方法はいくつかあります。

JavaScript配列のネイティブメソッドを使用できます。Vueはこれらのメソッドにフックするため、変更を検出できます。

これが_.splice_の使用例です

this.show.splice(index, 1, !this.show[index])

別の方法は、配列全体を置き換えることです。 ES6を使用している場合は、spread演算子を使用して配列を簡単に複製できます。

_this.show[index] = !this.show[index]
this.show = [...this.show]
_

_.map_は、新しい配列を返すため、機能します

_this.show = this.show.map((el, i) =>
  i === index ? !el : el
)
_
23
CodinCat

arrayの代わりにJS objectを使用して、同じ効果を得ることができます。つまり、show: [false, false, false],show: {0:false, 1:false, 2:false},

1
Igor de Lorenzi

メソッドのコンポーネントでは、次を使用できます。

this.$set(this.show, index, !this.show[index])
0
user5510975