文章簡(jiǎn)介
在本文之前已經(jīng)有文章簡(jiǎn)單概要介紹過(guò)vue中的渲染,點(diǎn)擊幫你快速?gòu)?fù)習(xí)????,包括條件渲染和列表渲染。
二者同樣重要,但是對(duì)于項(xiàng)目而言,使用更多的是列表渲染,主要表現(xiàn)為“循環(huán)”。 下面讓我們繼續(xù)深入地了解列表渲染的相關(guān)內(nèi)容吧~??????
v-for 主要內(nèi)容
??item in items
我們可以使用 v-for
指令基于一個(gè)數(shù)組來(lái)渲染一個(gè)列表。v-for
指令的值需要使用 item in items
形式的特殊語(yǔ)法,其中 items 是源數(shù)據(jù)的數(shù)組,而 item 是迭代項(xiàng)的別名。
【解釋一下:
item in items
可以理解為item是items中的一個(gè)迭代項(xiàng),可以是標(biāo)題元素,可以是各種類型的數(shù)據(jù)集合…等等,你都可以從把這些在也頁(yè)面中反復(fù)出現(xiàn)的內(nèi)容形式通過(guò)循環(huán),也就是v-for和item in items語(yǔ)法簡(jiǎn)單的表現(xiàn)出來(lái),實(shí)現(xiàn) 動(dòng)態(tài)綁定 的一個(gè)效果】
舉例說(shuō)明
ts
const items = ref([{ message: 'Foo' }, { message: 'Bar' }]) // 定義 items為一個(gè)響應(yīng)式數(shù)組 存放message的兩個(gè)元素信息
此時(shí),你可以思考一下,如果想把這兩個(gè)數(shù)據(jù)顯示在頁(yè)面里,是不是需要輸入兩次。而且是需要手動(dòng)讀取數(shù)據(jù)的,這樣顯然很不智能。如下:
<li>{{Foo}}</li>
<li>{{Bar}}</li>
元素個(gè)數(shù)越多,你所需要編寫的行數(shù)就越多,此時(shí)就需要循環(huán)的幫助,只需要v-for
加上一行模板語(yǔ)法,就能輕松實(shí)現(xiàn)效果。
template
<li v-for="item in items">
{{ item.message }}
</li>
在 v-for
塊中可以完整地訪問(wèn)父作用域內(nèi)的屬性和變量。v-for
也支持使用可選的第二個(gè)參數(shù)表示當(dāng)前項(xiàng)的位置索引。
ts
const parentMessage = ref('Parent')
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
template
<!-- index是item所在數(shù)組items中的下標(biāo)-->
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
運(yùn)行效果
v-for 變量的作用域
v-for的變量作用域和下面的 JavaScript 代碼很類似:
js
const parentMessage = 'Parent'
const items = [
/* ... */
]
items.forEach((item, index) => {
// 可以訪問(wèn)外層的 `parentMessage`
// 而 `item` 和 `index` 只在這個(gè)作用域可用
console.log(parentMessage, item.message, index)
})
注意 v-for
是如何對(duì)應(yīng) forEach
回調(diào)的函數(shù)簽名的。
實(shí)際上,你也可以在定義 v-for
的變量別名時(shí)使用解構(gòu),和解構(gòu)函數(shù)參數(shù)類似:
template
<li v-for="{ message } in items">
{{ message }}
</li>
<!-- 有 index 索引時(shí) -->
<li v-for="({ message }, index) in items">
{{ message }} {{ index }}
</li>
對(duì)于多層嵌套的 v-for
,作用域的工作方式和函數(shù)的作用域很類似。每個(gè) v-for
作用域都可以訪問(wèn)到父級(jí)作用域:
template
<li v-for="item in items">
<span v-for="childItem in item.children">
{{ item.message }} {{ childItem }}
</span>
</li>
你也可以使用 of
作為分隔符來(lái)替代 in
,這更接近 JavaScript 的迭代器語(yǔ)法:
template
<div v-for="item of items"></div>
v-for 與對(duì)象
你也可以使用 v-for
來(lái)遍歷一個(gè)對(duì)象的所有屬性。遍歷的順序會(huì)基于對(duì)該對(duì)象調(diào)用 Object.keys()
的返回值來(lái)決定。
ts
const myObject = reactive({
title: 'title',
author: 'GunGunxs',
publishedDate: '20221015'
})
template
<ul>
<li v-for="value in myObject">
{{ value }}
</li>
</ul>
可以通過(guò)提供第二個(gè)參數(shù)表示屬性名 (例如 key):
template
<li v-for="(value, key) in myObject">
{{ key }}: {{ value }}
</li>
第三個(gè)參數(shù)表示位置索引:
template
<li v-for="(value, key, index) in myObject">
{{ index }}. {{ key }}: {{ value }}
</li>
運(yùn)行結(jié)果:
在 v-for 里使用范圍值
v-for
可以直接接受一個(gè)整數(shù)值。在這種用例中,會(huì)將該模板基于1...n
的取值范圍重復(fù)多次。
<span v-for="n in 10">{{ n }}</span>
注意 此處 n 的初值是從 1 開(kāi)始而非 0。
??<template> 上的 v-for
可以在 標(biāo)簽上使用 v-for 來(lái)渲染一個(gè)包含多個(gè)元素的塊。
例如:
template
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
v-for 與 v-if
注意同時(shí)使用 v-if
和 v-for
是不推薦的,因?yàn)檫@樣二者的優(yōu)先級(jí)不明顯。
當(dāng)它們同時(shí)存在于一個(gè)節(jié)點(diǎn)上時(shí),v-if
比 v-for
的優(yōu)先級(jí)更高。這意味著 v-if
的條件將無(wú)法訪問(wèn)到 v-for
作用域內(nèi)定義的變量別名。
template
<!--
這會(huì)拋出一個(gè)錯(cuò)誤,因?yàn)閷傩詉tem此時(shí)
沒(méi)有在該實(shí)例上定義
-->
<li v-for="item in items" v-if="!item.isComplete">
{{ item.name }}
</li>
在外新包裝一層 <template>
再在其上使用 v-for
可以解決這個(gè)問(wèn)題 (這也更加明顯易讀):
template
<template v-for="item in items">
<li v-if="!item.isComplete">
{{ item.name }}
</li>
</template>
??通過(guò) key 管理狀態(tài)
vue 默認(rèn)按照 “就地更新” 的策略來(lái)更新通過(guò) v-for
渲染的元素列表。
- 當(dāng)數(shù)據(jù)項(xiàng)的順序改變時(shí),Vue 不會(huì)隨之移動(dòng) DOM 元素的順序,而是就地更新每個(gè)元素,確保它們?cè)谠局付ǖ乃饕恢蒙箱秩尽?/em>
默認(rèn)模式是高效的,但只適用于列表渲染輸出的結(jié)果不依賴子組件狀態(tài)或者臨時(shí) DOM 狀態(tài) (表單輸入值) 的情況。
- 為了給 vue 一個(gè)提示,以便它可以跟蹤每個(gè)節(jié)點(diǎn)的標(biāo)識(shí),從而重用和重新排序現(xiàn)有的元素,你需要為每個(gè)元素對(duì)應(yīng)的塊提供一個(gè)唯一的
key attribute
template
<div v-for="item in items" :key="item.id">
<!-- 內(nèi)容 -->
</div>
當(dāng)你使用 <template v-for>
時(shí),key
應(yīng)該被放置在這個(gè) <template>
容器上:
template
<template v-for="todo in todos" :key="todo.name">
<li>{{ todo.name }}</li>
</template>
注意
-
key
在這里是一個(gè)通過(guò)v-bind
綁定的特殊attribute
。 - 不要和在
v-for
中使用對(duì)象里所提到的對(duì)象屬性名相混淆。
推薦在任何可行的時(shí)候?yàn)?v-for
提供一個(gè) key attribute
,除非所迭代的 DOM 內(nèi)容非常簡(jiǎn)單 (例如:不包含組件或有狀態(tài)的 DOM 元素)
key
綁定的值期望是一個(gè)基礎(chǔ)類型的值,例如字符串或 number
類型。不要用對(duì)象作為 v-for 的 key。
<ul>
<li v-for="item in items" :key="item.id">...</li>
</ul>
??組件上使用 v-for
直接在組件上使用 v-for
,和在一般的元素上使用沒(méi)有區(qū)別 (別忘記提供一個(gè) key
)
template
<MyComponent v-for="item in items" :key="item.id" />
但這不會(huì)自動(dòng)將任何數(shù)據(jù)傳遞給組件(因?yàn)榻M件有自己獨(dú)立的作用域)為了將迭代后的數(shù)據(jù)傳遞到組件中,我們還需要傳遞 props
template
<MyComponent
v-for="(item, index) in items"
:item="item"
:index="index"
:key="item.id"
/>
??不自動(dòng)將 item 注入組件的原因是,這會(huì)使組件與 v-for
的工作方式緊密耦合。明確其數(shù)據(jù)的來(lái)源可以使組件在其他情況下重用。
------------------------------------------------------------------
????這是一個(gè)簡(jiǎn)單的 Todo List
的例子,展示了如何通過(guò) v-for
來(lái)渲染一個(gè)組件列表,并向每個(gè)實(shí)例中傳入不同的數(shù)據(jù)。
App.vue 中 TS部分
<script setup lang="ts">
import { ref } from 'vue'
import TodoItem from './TodoItem.vue' // 從外部引入
const newTodoText = ref('')
// 這里的todos當(dāng)然是可以從外部引入的
// 在項(xiàng)目中多采用模塊化 專門的東西放在專門的文件中
const todos = ref([
{
id: 1,
title: '吃飯'
},
{
id: 2,
title: '睡覺(jué)'
},
{
id: 3,
title: '學(xué)習(xí)'
}
])
let nextTodoId = 4 // 新增元素的id初始值為4
// 點(diǎn)擊事件觸發(fā)的添加事件
function addNewTodo() { // 這里的函數(shù)也可以使用箭頭函數(shù)
todos.value.push({
id: nextTodoId++, // id自增排在之前元素的下面
title: newTodoText.value // title
})
newTodoText.value = '' // 新增選項(xiàng)的內(nèi)容 這里設(shè)置為空
}
</script>
template部分
<template>
<!-- 綁定點(diǎn)擊事件 點(diǎn)擊添加事件-->
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input
v-model="newTodoText"
id="new-todo"
placeholder="請(qǐng)輸入一些東西"
/>
<button>Add</button>
</form>
<ul>
<todo-item
v-for="(todo, index) in todos"
:key="todo.id"
:title="todo.title"
@remove="todos.splice(index, 1)"
></todo-item>
<!-- 綁定todos中元素以及對(duì)應(yīng)的下標(biāo)
綁定他們各自的key值為其id屬性
綁定他們各自的title屬性
綁定點(diǎn)擊事件 點(diǎn)擊按鈕觸發(fā)刪除事件 -->
</ul>
</template>
TodoItem.vue中 TS部分
<script setup lang="ts">
defineProps(['title'])
defineEmits(['remove'])
</script>
template
<template>
<li>
{{ title }}
<button @click="$emit('remove')">Remove</button>
</li>
</template>
運(yùn)行效果:
來(lái)試試添加效果:
來(lái)試試刪除效果:
summary
以上就是v-for的深入展開(kāi),由本人結(jié)合資料和分析總結(jié)得出,若有不足和錯(cuò)誤,請(qǐng)大家及時(shí)指出,我會(huì)第一時(shí)間進(jìn)行修改!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-836523.html
下期預(yù)告
vue3【偵測(cè) 過(guò)濾】filter 數(shù)據(jù)變化偵測(cè)&信息篩選過(guò)濾
從鍵盤的敲擊聲中 感受知識(shí)的永恒律動(dòng)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-836523.html
到了這里,關(guān)于vue3【列表渲染】v-for 詳細(xì)介紹(vue中的“循環(huán)”)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!