リストのレンダリング


ディレクトリ


配列を要素のセットに対応させるには v-for を使用します

## を使用できます #v-for
ディレクティブは、配列に基づいてリストをレンダリングします。

v-for ディレクティブには、item in items という形式の特別な構文が必要です。ここで、items はソース データ配列、item はtarget 反復される配列要素の alias

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})
結果:

1.jpgv-for

ブロックでは、親スコープのすべてのプロパティにアクセスできます。

v-for は、オプションの 2 番目のパラメーターである現在の項目のインデックスもサポートします。

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
var example2 = new Vue({
  el: '#example-2',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})
結果:

2.jpgin

の代わりに

of を区切り文字として使用することもできます。 JavaScript イテレータに近い構文:

<div v-for="item of items"></div>


v-for## でのオブジェクトの使用 #v-for

を使用してオブジェクトのプロパティを走査することもできます。
<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }
})

結果:

2 番目のパラメータをプロパティ名 (つまり、キー名) として指定することもできます:

<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>
3.jpg

3 番目のパラメータをインデックスとして使用することもできます:

<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>

5.jpg

オブジェクトをトラバースするときは、Object.keys()# を押します。 ## 結果はトラバースされますが、 は、その結果が異なる JavaScript エンジンの下で一貫していることを保証できません。


メンテナンス状況

Vue が更新されている場合は
v を使用してください-for

要素のリストをレンダリングするとき、デフォルトでは「その場で更新」戦略が使用されます。データ項目の順序が変更された場合、Vue はデータ項目の順序に一致するように DOM 要素を移動しませんが、各要素をその場で更新し、各インデックス位置で正しくレンダリングされるようにします。これは、Vue 1.x の track-by="$index" に似ています。 このデフォルト モードは効率的ですが、

は子コンポーネントの状態や一時的な DOM 状態 (フォーム入力値など) に依存しないリスト レンダリング出力

にのみ適しています。 Vue にヒントを与えて各ノードの ID を追跡し、既存の要素を再利用したり並べ替えたりできるようにするには、各項目に一意の

key

属性を指定する必要があります。

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>
出力 DOM コンテンツの走査が非常に簡単な場合や、意図的にデフォルトに依存する場合を除き、

v-for

を使用する場合は、可能な限り key 属性を指定することをお勧めします。パフォーマンスを向上させるための行動。 これは Vue がノードを識別するための一般的なメカニズムであるため、

key

は特に v-for だけに関連するわけではありません。このガイドの後半で説明するように、他の用途もあります。

オブジェクトや配列などの非基本型の値を
v-for

key として使用しないでください。文字列または数値を使用してください。

key

属性の詳しい使用方法については、key の API ドキュメント を参照してください。


#配列更新の検出



##ミューテーション メソッド

Vue は、リッスンされた配列のミューテーション メソッドをラップするため、ビューの更新もトリガーされます。これらのラップされたメソッドには次のものが含まれます:

push()
  • pop()
  • #shift()

  • ##unshift()

  • splice()

  • sort()

  • reverse()

  • コンソールを開いて、前の例の items 配列に対する Mutation メソッドの呼び出しを試みることができます。たとえば、

    example1.items.push({ message: 'Baz' })
  • のようになります。

配列を置換


Mutation メソッドは、その名前が示すように、これらのメソッドが呼び出される元の配列を変更します。対照的に、filter()concat()slice() などの非変異メソッドもあります。元の配列は変更されず、 は常に新しい配列 を返します。非変更アプローチを使用する場合、古い配列を新しい配列で置き換えることができます。

example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})

これにより、Vue が既存の DOM を破棄し、リスト全体を再レンダリングすることになると思われるかもしれません。幸いなことに、そうではありません。 Vue は DOM 要素の再利用を最大限にするためにいくつかのスマート ヒューリスティックを実装しているため、元の配列を同じ要素を含む配列に置き換えることは非常に効率的な操作です。


注意事項

JavaScript の制限により、Vue は次のものを検出できません配列内の変更:

  1. インデックスを使用して配列項目を直接設定する場合、たとえば: vm.items[indexOfItem] = newValue

  2. 配列の長さを変更する場合、例: vm.items.length = newLength

例:

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

最初のタイプの問題を解決するには、次の 2 つのメソッドで vm.items[indexOfItem] = newValue と同じ効果を達成し、応答システムでのステータス更新もトリガーします。 :

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

グローバル メソッド Vue.set のエイリアスである vm.$set インスタンス メソッドを使用することもできます。

vm.$set(vm.items, indexOfItem, newValue)

2 番目のタイプの問題を解決するには、splice を使用できます:

vm.items.splice(newLength)


オブジェクト変更検出考慮事項


または、JavaScript の制限により、Vue はオブジェクト プロパティの追加または削除を検出できません:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的

すでに作成されたインスタンスの場合, Vue ではダイナミクスが許可されていません ルートレベルの応答性プロパティを追加します。ただし、Vue.set(object, propertyName, value) メソッドを使用して、ネストされたオブジェクトにリアクティブ プロパティを追加できます。たとえば、

var vm = new Vue({
  data: {
    userProfile: {
      name: 'Anika'
    }
  }
})

の場合、ネストされた userProfile オブジェクトに新しい age 属性を追加できます。

Vue.set(vm.userProfile, 'age', 27)

また、 # # を使用することもできます。 #vm.$set インスタンス メソッド。これはグローバル Vue.set:

vm.$set(vm.userProfile, 'age', 27)

のエイリアスにすぎません。場合によっては、複数の新しいプロパティを既存のオブジェクトに割り当てる必要がある場合があります。

Object.assign()_.extend() の使用など。この場合、両方のオブジェクトのプロパティを使用して新しいオブジェクトを作成する必要があります。したがって、新しい応答属性を追加する場合は、次のようにするのではなく、

Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

のようにする必要があります:

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})


フィルタリング/並べ替えられた結果の表示


元のデータを実際に変更またはリセットせずに、フィルタリングまたは並べ替えられた配列のバージョンを表示したい場合があります。この場合、フィルター処理または並べ替えられた配列を返す計算プロパティを作成できます。

例:

<li v-for="n in evenNumbers">{{ n }}</li>
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

計算されたプロパティが適用できない場合 (たとえば、ネストされた v-for ループ内)、次のメソッドを使用できます:

<li v-for="n in even(numbers)">{{ n }}</li>
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}


v-for


## の値の範囲を使用します#v-for は整数も受け入れます。この場合、テンプレートは対応する回数だけ繰り返されます。

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

結果:

1.jpg


##at

<template> を使用v-for

v-if
に似ていますが、

v-for 's# も使用できます。 ##<template> 複数の要素を含むコンテンツのレンダリングをループします。例:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>


v-for は v-if

と一緒に使用されます。 同じ要素で

v-if
v-for

を使用することは 推奨されないことに注意してください。詳細については、スタイル ガイドをご覧ください。 同じノード上にある場合、v-for

v-if
よりも優先されます。つまり、

v-if# です。 ## は、各 v-for ループ内で繰り返し実行されます。この優先順位メカニズムは、次のように、一部の項目のノードのみをレンダリングする場合に役立ちます。

<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>
上記のコードは、未完了の ToDo のみをレンダリングします。 そして、条件付きでループの実行をスキップすることが目的の場合は、外部要素 (または <template> #) に

v-if

を配置できます。 #####)優れた。例:

<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>

v-for


を使用します。コンポーネント ## このパートは、読者が コンポーネント


に関する知識をすでに持っていることを前提としています。スキップして後で戻ってくることもできます。

カスタム コンポーネントでは、通常の要素と同じように v-for を使用できます。

<my-component v-for="item in items" :key="item.id"></my-component>

バージョン 2.2.0 では、コンポーネントで
v-for

を使用するときに key が必要になりました。

ただし、コンポーネントには独自の独立したスコープがあるため、データはコンポーネントに自動的に渡されません。反復データをコンポーネントに渡すには、prop:

<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>

を使用する必要があります。item がコンポーネントに自動的に挿入されない理由は、これによってコンポーネントが異なるものになるためです。 v-for の操作は密接に結合されています。コンポーネントのデータのソースを明確にすると、コンポーネントを他の状況で再利用できるようになります。

これは、単純な todo リストの完全な例です:

<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    >
    <button>Add</button>
  </form>
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>

ここの is="todo-item" 属性に注意してください。 <ul> 要素内の <li> 要素のみが有効なコンテンツとみなされないため、DOM テンプレートを使用する場合、このアプローチは非常に必要です。これにより、<todo-item> と同じ効果が得られますが、潜在的なブラウザ解析エラーを回避できます。詳細については、DOM テンプレートの解析手順を参照してください。

Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">Remove</button>\
    </li>\
  ',
  props: ['title']
})
new Vue({
  el: '#todo-list-example',
  data: {
    newTodoText: '',
    todos: [
      {
        id: 1,
        title: 'Do the dishes',
      },
      {
        id: 2,
        title: 'Take out the trash',
      },
      {
        id: 3,
        title: 'Mow the lawn'
      }
    ],
    nextTodoId: 4
  },
  methods: {
    addNewTodo: function () {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})

1.gif