こんにちは、Xiao Suoqiha です。丁寧に作られた Vue シリーズを継続的に配布し、多数の経験と事例を網羅し、浅いところから深いところまで解説しています。この章では、条件付きレンダリングとリスト レンダリングについて説明します。前の章は更新され、次の章は引き続き出力されます。質問がある場合は、メッセージを残すか、プライベート メッセージを送信できます。一緒に働きましょう~
条件付きレンダリング
1.v-if
このディレクティブは、式が true か false に基づいて要素をレンダリングするかどうかを決定します。
例えば:
<div v-if="show">
只有在 show = true 时显示
</div>
2. v-else-if/v-else
v-else-if は v-if の「else-if」条件を表し、v-else は最後の「else」条件を表します
例えば:
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else>
都不是
</div>
3. キーを使用して再利用可能な要素を管理する
Vue にキー値を通じて要素を識別させ、レンダリング効率を向上させます
例えば:
<div v-if="loginType === 'username'" key="username">
username
</div>
<div v-else key="email">
email
</div>
4.vショー
CSSに基づいて要素の表示/非表示を切り替え、表示を切り替えるだけ
例えば:
<div v-show="ok">
在 ok=true 时显示
</div>
頻繁に変更したい場合は、v-show
非表示の表示を切り替えるだけなので効率的です。
条件付きレンダリングにおけるv-if、v-showの選択判定は以下の通りです。
-
ユーザー権限制御など、要素の表示/非表示を完全に切り替える必要がある場合は、DOMを直接操作して要素を完全に破棄または再描画するv-ifを使用します。
-
一部のポップアップウィンドウやプロンプトなど、単純に要素の表示/非表示を切り替えるだけの場合は、CSS の表示属性のみを切り替える v-show を使用するとオーバーヘッドが少なくなります。
-
要素が単純でレンダリングのオーバーヘッドが小さい場合は両者に大きな差はありませんが、要素がより複雑な場合は v-show の方が若干高速になります。
-
頻繁に切り替える必要がある場合は v-show を使用し、実行時に変更が発生する可能性が低い場合は v-if を使用します。
簡単に要約すると、次のようになります。
-
v-if を使用して完全に表示/非表示にします
-
v-show を使用して簡単に表示/非表示を切り替えます
-
頻繁な切り替えには v-show を使用する
-
実行時に v-if を変更せずに使用する
テンプレート上の v-if
template
Element は複数の要素を保持できる非表示のラッパーですが、DOM 自体にはレンダリングされません。
一般的なアプリケーション シナリオは、v-if 命令と組み合わせて使用することです。
-
v-if を追加すると、複数の内部要素
<template>
を条件付きでレンダリングできます<template>
。 -
v-if を単一の要素に直接追加するような、v-if の条件判断を何度も繰り返し記述する必要はありません。
-
<template>
あらゆるタイプの要素を含めることができ、要素ブロックを非常に便利に整理できます -
最終的なレンダリング結果には要素は含まれず
<template>
、その内部の要素のみが含まれます。
ユーザー情報表示ケース
<template v-if="user.loggedIn">
<div>
<!-- 用户信息 -->
<p>用户名:{
{user.name}}</p>
<p>积分:{
{user.points}}</p>
</div>
<div>
<!-- 用户菜单 -->
<button>首页</button>
<button>设置</button>
</div>
</template>
<div v-else>
<!-- 登录提示 -->
<p>请登录后查看个人信息</p>
<button>去登录</button>
</div>
テンプレートは v-if でのみ使用でき、v-show では使用できないことに注意してください。
リストのレンダリング
v-for
データに基づいて要素を複数回レンダリングするために使用され、通常はリスト データをレンダリングするために使用されます
<ul>
<li v-for="item in list">
{
{ item }}
</li>
</ul>
テンプレート v-for
v-if と同様に、<template>
v-for を使用して要素のブロックをレンダリングできます。
<template v-for="item in list">
<div>{
{item.name}}</div>
<div>{
{item.desc}}</div>
</template>
トラックバイ
レンダリング効率を向上させるために要素の一意の識別子を指定するために使用されます。
<div v-for="item in list" :key="item.id"></div>
キーの詳しい説明はこちら
Vue リストをレンダリングするときは、li 要素の長いリストを生成する todolist アプリケーションに似ています。リスト データが更新されると、Vue は挿入、削除、並べ替えなど、どの要素が変更されたかを認識する必要があります。
では、Vue はどのようにして各要素の ID を識別するのでしょうか? これがキーの役割です。
さまざまな要素を識別するには、各要素に一意のキー値を追加する必要があります。
<ul>
<li v-for="item in list" :key="item.id">
{
{item.name}}
</li>
</ul>
ここでは、各データ項目の ID をキー key として使用します。要件は一意です。たとえば、項目の ID はキーとして非常に適しています。
キーを使用すると、Vue はどの要素が変更されたかを正確に知ることができ、たとえば、要素が削除された場合、Vue はキーに対応する要素を見つけてそれを破棄します。
これにより、効率的なリストのレンダリングが可能になります。
簡単に言うと、キーは Vue リストのレンダリングのパフォーマンスを向上させるために要素の一意の識別子として使用されます。最下層は DOM ノードを再利用します。キーは一意である必要があり、インデックスをキーとして使用しないことに注意してください。
知らせ
必ずキーを書いてください!キーを書き込まなければエラーは報告されないとされていますが、キーの書き込みに失敗すると次のような結果が生じる可能性があります。
-
リストが再レンダリングされると、元の要素は移動されずに新しい要素が直接作成されるため、ページがちらつく原因になります。
-
Transition遷移アニメーションを使用する場合、要素の状態が正しく取得できません。
-
リスト要素を識別する Vue の内部機能が失われ、他の問題が発生する
ここでは以下の点のみ記載していますが、reactにキーを書かないと直接エラーが報告されます。
キーを記述しない場合、Vue は自動的にインデックスをキーとして使用します (インデックスについては後述します)。
-
vm.items[0] = {} など、インデックスを介して配列を直接変更すると、応答しません。配列は、Vue.set(vm.items, 0, {}) または vm.items.splice() を使用して変更する必要があります。
公式サイトのご紹介
画像-20230821000956765
索引
インデックス値は 2 番目のパラメータを通じて取得できます。
<div v-for="(item, index) in list"></div>
上記のキーはインデックスに基づいて定義することもできます
<div v-for="(item, index) in list"></div>
ここに問題があるかもしれません。インデックスをキーとして使用できますか? 可能ですが、お勧めしません。
たとえば、次のような場合
<li v-for="(item, index) in list" :key="index">
{
{ item }}
</li>
インデックスをキーとして使用すると、次の問題が発生します。
-
リストの順序を変更すると、要素のキーが変更され、状態が混乱します (たとえば、インデックス 0 の新しい小さな Suoqi が追加され、Zhang San が初期インデックス 0 に置き換えられます。元のリストと比較すると、チャン・サンがシャオ・スオチーによって変えられたことが判明。スオ・チーは逃げました、これは大したことではありませんか?)
-
変更の原因がインデックスの変更なのかデータの変更なのかを正確に判断できない
-
要素が削除されると、生成された新しいインデックスは元の要素を追跡しません。
これを記述する正しい方法は、それをitem.id
本文にバインドし、データの各項目の安定した一意の識別子をキーとして使用することです。
面接の質問の形で存在することに注意してください
画像-20230821002410628
拡張された差分アルゴリズム
キーは仮想 DOM オブジェクトの識別子であり、データが変更されると、Vue は新しいデータに基づいて新しい仮想 DOM を生成します。
diff アルゴリズムは、Vue や React などの仮想 DOM フレームワークで効率的な DOM 更新を実現するための重要なアルゴリズムであり、ビューを段階的に更新し、DOM ツリー全体の再レンダリングを回避できます。
diff アルゴリズムの基本原理は次のとおりです。
-
現在の仮想 DOM と最後の仮想 DOM を比較して、変更された内容を確認します (直接変更されていないものは再利用します)。
-
新しい仮想ノードと同じキーが古い仮想ノードに見つからない場合は、直接新しい仮想 DOM を作成してレンダリングし、キーが同じであれば内容を比較します。
-
DOM を直接操作するのではなく、JS オブジェクトへの変更を記録します。
-
これらの変更を実際の DOM ツリーに一度に更新します
簡単な例
diff アルゴリズムを比較すると、B を C に置き換えるだけで済むことがわかります。UL 全体を再レンダリングする必要がないため、不必要な DOM 操作が回避されます。
<!-- 上次虚拟DOM -->
<ul>
<li>A</li>
<li>B</li>
</ul>
<!-- 当前虚拟DOM -->
<ul>
<li>A</li>
<li>C</li>
</ul>
Vue と React はどちらも同様の差分アルゴリズムを使用して実際の DOM への更新を最小限に抑え、非常に高いパフォーマンス上の利点をもたらします。
画像-20230821005540298
配列更新の検出
Vue には、ビューを応答的に更新するための一連の観測配列突然変異メソッドが含まれています
プッシュ、ポップ、スプライスなどのメソッド。
リストフィルター
2 セットのコードを使用してそれぞれフィルタリング効果を実現します
実装を監視する
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅、',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'}
],
//存放过滤后的新数组
filPerons:[]
},
watch:{
keyWord:{
immediate:true,
handler(val){
this.filPerons = this.persons.filter((p)=>{
// 返回一个布尔值
return p.name.indexOf(val) !== -1
})
}
}
}
})
計算された実装
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'}
]
},
computed:{
filPerons(){
// 计算属性必备return
return this.persons.filter((p)=>{
// 返回一个布尔值,计算属性没有newValue属性,但可以通过用户输入的值来拿
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
最初は、計算されたプロパティはデフォルトで get を呼び出しますが、依存データが変更されると、フィルタリングを実現するために計算されたプロパティも自動的に呼び出されます。
computed と watch の両方が実装できる場合は、computed が優先されます。
フィルターを展開する
filter メソッドの機能は次のとおりです。
-
関数をパラメータとして受け取り、配列内の各要素を 1 つずつ処理します。
-
この関数はブール値を返します。true は要素を保持することを意味し、false は要素をフィルタリングすることを意味します
-
フィルタは、関数が true を返す要素を含む新しい配列を返します。
-
次の例の名前はコールバック関数のパラメーターを表し、現在スキャンされている配列要素を示します。
const names = ['王美丽', '李小福', '张快乐', '赵细腻', '吉祥如意', '康健壮'];
const longNames = names.filter(name => name.length > 3);
const loudLongNames = longNames.map(name => name.toUpperCase());
console.log(loudLongNames);
// 输出:['李小福', '张快乐', '赵细腻', '吉祥如意']
ここでは、3 文字を超える中国語名をフィルターで除外し、大文字に変換します。これは、もう 1 つの方法を使用するためです~
filter の最も一般的な使用法は、配列をフィルタリングし、判定条件を受け入れ、新しいフィルタリングされた配列を返すことです。
リストの並べ替え
事例: フィルタリング + ソートを実装する
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="(p,index) of filPerons" :key="p.id">
{
{p.name}}-{
{p.age}}-{
{p.sex}}
<input type="text">
</li>
</ul>
</div>
<script type="text/JS">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
keyWord:'',
sortType:0, //0原顺序 1降序 2升序
persons:[
{id:'001',name:'马冬梅',age:30,sex:'女'},
{id:'002',name:'周冬雨',age:31,sex:'女'},
{id:'003',name:'周杰伦',age:18,sex:'男'},
{id:'004',name:'温兆伦',age:19,sex:'男'}
]
},
computed:{
filPerons(){
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
//判断一下是否需要排序
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
})
</script>
画像.png
拡大する
配列.sort()
const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// output: Array ["Dec", "Feb", "Jan", "March"]
const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// output: Array [1, 100000, 21, 30, 4]
比較関数が提供されている場合compareFn
、undefined
以外のすべての配列要素は比較関数の戻り値に従ってソートされ、すべてのundefined
要素は配列の最後までソートされ、呼び出しは行われません。compareFn
画像-20230822221418048
シンプルなケース
let arr = [66,99,88]
arr.sort((a,b)=>{
// 前-后就是升序,相反则降序
return a-b
})
console.log(arr)
// [66, 88, 99]
役に立ったら、無料愛をクリックしてください〜