リストのレンダリング
ディレクトリ
- ##v-for 値の範囲での使用
- v- で使用するには、<テンプレート> で
- #v- に v- を使用します。 if
- コンポーネントで v-for を使用する
配列を要素のセットに対応させるには 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' } ] } })結果:
v-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' } ] } })
結果:
in
の代わりに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' } } })
結果:
<div v-for="(value, name) in object"> {{ name }}: {{ value }} </div>
3 番目のパラメータをインデックスとして使用することもできます:
<div v-for="(value, name, index) in object"> {{ index }}. {{ name }}: {{ value }} </div>
オブジェクトをトラバースするときは、
Object.keys()# を押します。 ## 結果はトラバースされますが、
は、その結果が異なる JavaScript エンジンの下で一貫していることを保証できません。
メンテナンス状況
Vue が更新されている場合はv を使用してください-for
要素のリストをレンダリングするとき、デフォルトでは「その場で更新」戦略が使用されます。データ項目の順序が変更された場合、Vue はデータ項目の順序に一致するように DOM 要素を移動しませんが、各要素をその場で更新し、各インデックス位置で正しくレンダリングされるようにします。これは、Vue 1.x の track-by="$index"
に似ています。 このデフォルト モードは効率的ですが、
にのみ適しています。 Vue にヒントを与えて各ノードの ID を追跡し、既存の要素を再利用したり並べ替えたりできるようにするには、各項目に一意の
key 属性を指定する必要があります。
出力 DOM コンテンツの走査が非常に簡単な場合や、意図的にデフォルトに依存する場合を除き、<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>
を使用する場合は、可能な限り key
属性を指定することをお勧めします。パフォーマンスを向上させるための行動。 これは Vue がノードを識別するための一般的なメカニズムであるため、
は特に v-for
だけに関連するわけではありません。このガイドの後半で説明するように、他の用途もあります。
v-forkeyの
key
として使用しないでください。文字列または数値を使用してください。
属性の詳しい使用方法については、key の API ドキュメント
を参照してください。
##ミューテーション メソッド
Vue は、リッスンされた配列のミューテーション メソッドをラップするため、ビューの更新もトリガーされます。これらのラップされたメソッドには次のものが含まれます:
push()
pop()-
#shift()
##unshift()
splice()
sort()
reverse()
コンソールを開いて、前の例の
example1.items.push({ message: 'Baz' })items
配列に対する Mutation メソッドの呼び出しを試みることができます。たとえば、 のようになります。
Mutation メソッドは、その名前が示すように、これらのメソッドが呼び出される元の配列を変更します。対照的に、filter()
、concat()
、slice()
などの非変異メソッドもあります。元の配列は変更されず、 は常に新しい配列 を返します。非変更アプローチを使用する場合、古い配列を新しい配列で置き換えることができます。
example1.items = example1.items.filter(function (item) { return item.message.match(/Foo/) })
これにより、Vue が既存の DOM を破棄し、リスト全体を再レンダリングすることになると思われるかもしれません。幸いなことに、そうではありません。 Vue は DOM 要素の再利用を最大限にするためにいくつかのスマート ヒューリスティックを実装しているため、元の配列を同じ要素を含む配列に置き換えることは非常に効率的な操作です。
注意事項
JavaScript の制限により、Vue は次のものを検出できません配列内の変更:
インデックスを使用して配列項目を直接設定する場合、たとえば:
vm.items[indexOfItem] = newValue
配列の長さを変更する場合、例:
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>結果:
<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-ifをご覧ください。
同じノード上にある場合、v-for は
v-if# です。 ## は、各 v-for
ループ内で繰り返し実行されます。この優先順位メカニズムは、次のように、一部の項目のノードのみをレンダリングする場合に役立ちます。
上記のコードは、未完了の ToDo のみをレンダリングします。 <li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
そして、条件付きでループの実行をスキップすることが目的の場合は、外部要素 (または
<template> #) に
を配置できます。 #####)優れた。例:
<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カスタム コンポーネントでは、通常の要素と同じように v-for を使用できます。
<my-component v-for="item in items" :key="item.id"></my-component>バージョン 2.2.0 では、コンポーネントで
を使用するときに 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 = '' } } })