iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 8
0
自我挑戰組

網頁前端框架 Vue 3 從頭開始系列 第 8

vue.js 3.x 學習手冊 (8) v-for為何要定義key呢?

講到了v-for和v-bind就不得不提key的這個屬性,主要就是要討論透過v-for所渲染的項目,在資料更新時會怎麼處理,若在v-for渲染的項目中“沒有”加入key屬性(如上面的範例),預設的行為是當數據順序改變時,vue會透過“就地更新(In-place patch)”的策略進行變更,也就是說Vue不會移動任何DOM元素來配合數據順序,只是就地去更新項目內容確保他們在每個索引位置正確的渲染。

透過上述的方式能夠增強網頁的效能,但有時候並沒有辦法達到我們期望的效果,我們透過下面的範例進行說明:

HTML
<div id="app">
    <h3>Please make your choice:</h3>
    <ul>
        <li v-for="item in names">
            {{ item.title }} : 
            <select>
                <option disabled value="" selected>Please select one</option>
                <option v-for="(item, index) in types" :value="item.value">{{ item.title }}</option>
            </select>
        </li>
    </ul>
    <p>
        <button @click="sortASC">Sort by Name ASC</button>
        <button @click="sortDESC">Sort by Name DESC</button>
    </p>
</div>
Javascript
const app = Vue.createApp({
    data() {
        return {
            names:[
                {title: "Vue", value: "Vue"},
                {title: "React", value: "React"},
                {title: "Angular", value: "Angular"},
                {title: "Laravel", value: "Laravel"},
                {title: "CakePHP", value: "CakePHP"},
                {title: "Django", value: "Django"},
            ],
            types:[
                {title: "Frontend", value: "Frontend"},
                {title: "Backend", value: "Backend"},
            ],
        }
    },
    methods:{
        sortASC() {
            this.names = this.names.sort(function (a, b) {
                return a.title > b.title ? 1 : -1;
            });
        },
        sortDESC() {
            this.names = this.names.sort(function (a, b) {
                return b.title > a.title ? 1 : -1;
            });
        },
    }
}).mount('#app');

大家可以先想像一下這是一個小測驗的網頁,在頁面中有六個選項,選項旁邊有個下拉選單讓使用者挑選正確答案,然後比較重要的是下面有兩個按鈕,可以讓數列按字母重新排序,當使用者選完旁邊的選項之後,再按下重新排序的按鈕,你就會發現,雖然數據重新渲染,但因為沒有更新DOM的順序,所以會發生項目還使用者選取的結果對不起來的問題!

範例檔

解決方案就是在需要透過v-for渲染的tag中加入key屬性,也就是只要更新上面HTML的第4行如下:

<li v-for="item in names" :key="item.title">

就可以得到下面這個範例的結果囉!範例檔

要注意給的key值是不能有重複的,否則頁面會發生錯誤,也不建議使用index當做Key值,因為若爾後插入值在數列中,就會造成渲染錯誤,大家可以依據自己在頁面中的需求,來考量是否需要在v-for中加入key屬性(當然很多人選擇無腦加)。

v-for 參數

除了能透過Value來產生數列外,也可以透過以下的方式來取得物件的Key與Index值:

HTML
<div id="app">
    <ul>
        <li v-for="(value, name, index) in frameworks">
            {{ index + 1 }}. {{ name }} - {{ value }}
        </li>
    </ul>
</div>
Javascript
const app = Vue.createApp({
    data() {
        return {
            frameworks: {
                Vue: "Frontend",
                React: "Frontend",
                Angular: "Frontend",
                Laravel: "Backend",
                CakePHP: "Backend",
                Django: "Backend",
            },
        }
    },
}).mount('#app');

好啦!今天的文章就先到這裡,明天繼續跟大家介紹vue中方便又好用的功能。


上一篇
vue.js 3.x 學習手冊 (7) 清單渲染
下一篇
vue.js 3.x 學習手冊 (9) 計算屬性
系列文
網頁前端框架 Vue 3 從頭開始10

1 則留言

0
yolala
iT邦新手 5 級 ‧ 2020-09-09 16:47:36

簡單來說可以這樣理解嗎 如果在v-for 裡面沒有 放key 有可能無法渲染正確位置?、

史坦利 iT邦新手 5 級 ‧ 2020-09-09 17:56:48 檢舉

Hi yolala:
可以理解成網頁初期渲染的時候能在正確的位置,但若資料更新後可能會被誤判成沒有更新而導致各種錯誤的發生。

所以許多的網頁設計者會無腦的在裡面加上Unique key,避免各種會發生錯誤的機會。

我要留言

立即登入留言