vue.js - 循環(huán)渲染

vue.js 循環(huán)渲染

[TOC]

一谣光、簡(jiǎn)介

vue.js 的循環(huán)渲染是依賴于 v-for 指令,它能夠根據(jù) vue 的實(shí)例里面的信息,循環(huán)遍歷所需數(shù)據(jù)野瘦,然后渲染出相應(yīng)的內(nèi)容。它可以遍歷數(shù)組類型以及對(duì)象類型的數(shù)據(jù)飒泻,js 里面的數(shù)組本身實(shí)質(zhì)上也是對(duì)象鞭光,這里遍歷數(shù)組和對(duì)象的時(shí)候,方式相似但又稍有不同泞遗。

(一)遍歷對(duì)象

<div id="app">
    <ul>
        <li v-for="(val, key, index) in me">{{index}}. {{key}}: {{val}}</li>
    </ul>
</div>
...
var vm = new Vue({
    el: '#app',
    data: {
        me: {
            name: 'Dale',
            age: 22,
            sex: 'male',
            height: 170
        }
    }
});

這里惰许,v-for 接收的參數(shù)相對(duì)較復(fù)雜,但是可以分為三個(gè)部分:

(1)括號(hào)及其內(nèi)的遍歷結(jié)果信息(val, key, index)

其中史辙,val 是遍歷得到的屬性值汹买,key 是遍歷得到的屬性名,index 是遍歷次序聊倔,這里的 key/index 都是可選參數(shù)晦毙,如果不需要,這個(gè)指令其實(shí)可以寫成 v-for="val in me"耙蔑;

(2)遍歷關(guān)鍵詞 in

in 可以使用 of 替代见妒,官方的說(shuō)法是“它是最接近 JavaScript 迭代器的語(yǔ)法”,但其實(shí)使用上并沒(méi)有任何區(qū)別甸陌;

(3)被遍歷對(duì)象 me

me 是綁定在實(shí)例 data屬性上的一個(gè)屬性须揣,實(shí)際上盐股,它是有一個(gè)執(zhí)行環(huán)境的,也即是我們接觸最多的 vue 實(shí)例返敬,模板中遂庄,我們?nèi)耘f可以像在 methods 以及計(jì)算屬性中一樣,通過(guò) this 訪問(wèn)到它劲赠,這里的 me 其實(shí)就相當(dāng)于 this.me涛目,模板中直接寫 this.me 也是可行的。
渲染結(jié)果如下:

<div id="app">
    <ul>
        <li>0. name: Dale</li>
        <li>1. age: 22</li>
        <li>2. sex: male</li>
        <li>3. height: 170</li>
    </ul>
</div>

(二)遍歷數(shù)組

<div id="app">
    <ul>
        <li v-for="(item, index) in items">{{index}}. {{item}}</li>
    </ul>
</div>
...
var vm = new Vue({
    el: '#app',
    data: {
        items: ['apple', 'tomato', 'banana', 'watermelon']
    }
});

和遍歷對(duì)象相類似凛澎,最大的不同點(diǎn)在于對(duì)象的 “key” 和 “index” 是一致的霹肝,所以這里我們只需要取一個(gè) index 即可,上面代碼的渲染結(jié)果如下:

<div id="app">
    <ul>
        <li>0. apple</li>
        <li>1. tomato</li>
        <li>2. banana</li>
        <li>3. watermelon</li>
    </ul>
</div>

(三)遍歷“整數(shù)”

理論上來(lái)說(shuō)塑煎,整數(shù)并不是一個(gè)可遍歷的單元沫换,但是 vue 這里相當(dāng)于給我們提供了一個(gè)方便方式來(lái)減少重復(fù)代碼。

<div id="app">
    <ul>
        <li v-for="n in num">{{n}}</li>
    </ul>
</div>
...
var vm = new Vue({
    el: '#app',
    data: {
        num: 3
    }
});

渲染結(jié)果如下:

<div id="app">
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
</div>

二最铁、實(shí)際應(yīng)用

(一)對(duì)象讯赏、數(shù)組 & 組件

實(shí)際應(yīng)用過(guò)程中,我們單獨(dú)使用數(shù)組或者對(duì)象去描述我們的數(shù)據(jù)的情況很少冷尉,更常見(jiàn)的模式是結(jié)合了數(shù)組和對(duì)象兩部分內(nèi)容:

<div id="app">
     <ul class="persons">
        <li v-for="person in persons">name: {{person.name}}, age: {{person.age}};</li>
    </ul> 
</div>
...
var vm = new Vue({
    el: '#app',
    data: {
        persons: [
            {
                name: 'Dale',
                age: 22
            }, 
            {
                name: 'Tim',
                age: 30
            },
            {
                name: 'Rex',
                age: 23
            }
        ]
    }
});

本質(zhì)上是遍歷的一個(gè)數(shù)組漱挎,但是數(shù)組的每個(gè)元素卻是一個(gè)對(duì)象,也就是上面的 person雀哨,我們可以通過(guò) [] 以及 . 兩種方式去訪問(wèn)這個(gè)對(duì)象的屬性磕谅,比如這里的 name / age,渲染結(jié)果如下:

<div id="app">
    <ul class="persons">
        <li>name: Dale, age: 22;</li>
        <li>name: Tim, age: 30;</li>
        <li>name: Rex, age: 23;</li>
    </ul>
</div>

實(shí)際上雾棺,更加常用且強(qiáng)大的模式膊夹,是使用組件與數(shù)組/對(duì)象進(jìn)行組合,操作方式與上面相類似捌浩。
(二)與 v-if 組合
添加了 v-for 指令的標(biāo)簽放刨,實(shí)際上也可以同時(shí)添加 v-if 指令,但值得注意的是尸饺,v-for 的優(yōu)先級(jí)更高宏榕,渲染模板時(shí),相當(dāng)于對(duì)每次遍歷的結(jié)果進(jìn)行了一次條件判斷侵佃。

<div id="app">
     <ul class="persons">
        <li v-for="person in persons" v-if="person.age >= 23">name: {{person.name}}, age: {{person.age}};</li>
    </ul> 
</div>
...
var vm = new Vue({
    el: '#app',
    data: {
        persons: [
            {
                name: 'Dale',
                age: 22
            }, 
            {
                name: 'Tim',
                age: 30
            },
            {
                name: 'Rex',
                age: 23
            }
        ]
    }
});

這里先遍歷了 persons 的所有元素,然后檢查每次得到的 person 的是否大于或等于 23奠支,是則輸出馋辈,否則不輸出,渲染結(jié)果如下:

<div id="app">
    <ul class="persons">
        <li>name: Tim, age: 30;</li>
        <li>name: Rex, age: 23;</li>
    </ul>
</div>

如果要讓 v-if 指令的優(yōu)先級(jí)更高倍谜,可以考慮在 v-for 指令所綁定的標(biāo)簽的父級(jí)上添加 v-if 指令迈螟。

三叉抡、注意事項(xiàng)

(一)key

v-for 一樣,在不綁定 key 屬性的情況下答毫,vue 默認(rèn)會(huì)重用元素以提高性能褥民,如果不需要它的默認(rèn)行為,顯式綁定一個(gè)唯一的 key 即可洗搂。

(二)數(shù)據(jù) -> 視圖更新

vue 的視圖更新是依賴于 getter/setter 的消返,如果直接修改、增加耘拇、刪除數(shù)組元素撵颊,并不會(huì)觸發(fā)視圖的更新。這里 vue 重寫了如下方法:

push
pop
shift
unshift
splice
sort
reverse

當(dāng)通過(guò)它們修改數(shù)據(jù)的時(shí)候惫叛,將會(huì)觸發(fā)視圖的更新倡勇。

new Vue({
    data: {
        arr: [1, 2, 3]
    }
});

比如上面這種情況,如果我們想要在執(zhí)行 arrpush 等方法嘉涌,因?yàn)?push 是數(shù)組類型數(shù)據(jù)從 Array.prototype.push 繼承過(guò)來(lái)的妻熊,所以我們一般情況下有兩種實(shí)現(xiàn)方式。
(1)修改 Array.prototype

Array.prototype.push = function () {
    console.log(1);
}
([]).push();               // 1

這里我們修改了 Array.prototype 上的 push 方法仑最,但是實(shí)際上扔役,整個(gè) prototype 屬性都可以被重寫,如 Array.prototype = xxx词身,這樣做的好處很明顯厅目,在這一處進(jìn)行修改,之后所有的數(shù)組類型都可以直接使用這個(gè)重寫后的方法法严,實(shí)現(xiàn)和使用都非常簡(jiǎn)單损敷;但是這樣帶來(lái)的副作用也特別明顯,容易影響到其它的代碼深啤,其它使用這段代碼的地方拗馒,除了功能實(shí)現(xiàn)上可能受到影響外,效率上也會(huì)有較大影響溯街,原生 js 的代碼都是經(jīng)過(guò)特殊優(yōu)化的诱桂,我們重寫實(shí)現(xiàn),效率肯定會(huì)受到影響呈昔,最重要的是挥等,如果大家的代碼在同一個(gè)環(huán)境下運(yùn)行,然后都嘗試重寫同一個(gè)方法的話堤尾,最終結(jié)果不言而喻肝劲。
(2)增加自有方法

var arr = [];

arr.push = function () {
    console.log(1);
}

arr.push();                  // 1
Array.prototype.push.toString();    // "function push() { [native code] }"

這里修改了 arrpush 方法, 但是并不涉及 Array.prototype.push,因?yàn)樽x寫一個(gè)對(duì)象的屬性/方法的時(shí)候辞槐,js 總是先嘗試訪問(wèn) “ownproperty”掷漱,也就是 “hasOwnProperty” 所檢測(cè)的內(nèi)容,這里我們姑且將其稱為“自有屬性(方法)”榄檬。讀取數(shù)據(jù)的時(shí)候卜范,如果沒(méi)有讀取到內(nèi)容,那么 js 會(huì)嘗試向上搜索 __proto__ 上的數(shù)據(jù)鹿榜;寫數(shù)據(jù)的時(shí)候海雪,如果有這個(gè)自有屬性,則會(huì)將其覆蓋犬缨,如果沒(méi)有喳魏,則將其作為自有屬性添加到改對(duì)象上,而不會(huì)嘗試將其添加到 __proto__ 上怀薛,這樣的規(guī)則刺彩,也是為了防止“子類”以外修改“父類”的屬性、方法等枝恋。這種實(shí)現(xiàn)方式雖然可以避免上面修改 Array.prototype 的一系列缺點(diǎn)创倔,但是它的問(wèn)題就更加明顯,因?yàn)槊看蝿?chuàng)建這樣一個(gè)“數(shù)組”焚碌,就要重新實(shí)現(xiàn)/綁定這樣一系列方法畦攘,它所帶來(lái)的開(kāi)發(fā)效率、性能問(wèn)題不容小覷十电。
(3)vue 的實(shí)現(xiàn)方式

var arr = [];
new Vue({
    data: {
        arr: arr
    }
});

arr.push.toString();        // "function mutator() {var arguments$1 = arguments;...  這是 vue 自己的實(shí)現(xiàn)
Array.prototype.push.toString();      // "function push() { [native code] }"...  這是瀏覽器原生的實(shí)現(xiàn)
arr.hasOwnProperty('push');           // false  說(shuō)明不是自有屬性

以上說(shuō)明 vue 既不是修改了 Array.prototype.push知押,又不是修改了自有屬性。但我們通過(guò) instanceof 操作符檢查的時(shí)候鹃骂,arr 又是 Array 的一個(gè)實(shí)例,那么它到底是怎么弄的實(shí)現(xiàn)的呢台盯?或者說(shuō) vue 的 push 藏在哪兒呢?

var base = [];
var arr = [];

base.push = function () {
    console.log(1);
};
arr.__proto__ = base;
arr.push();          // 1
arr.__proto__.push(); // 1
arr.__proto__.push.toString();  // "function push() { [native code] }"

實(shí)際上畏线,vue 是利用了類似上面的方式静盅,先創(chuàng)建了一個(gè) Array 的實(shí)例,也就是一個(gè)數(shù)組類型的基礎(chǔ)對(duì)象 base寝殴,然后為它添加了一個(gè)自有方法 push蒿叠,最后用 base 覆蓋了需要擴(kuò)展的 arr 對(duì)象的 __proto__ 屬性。

__proto__.png

這里需要重寫 push 等方法的數(shù)組蚣常,我們只需要將其 __proto__ 指向 base 數(shù)組市咽,在讀新創(chuàng)建的數(shù)組的 push 的時(shí)候,發(fā)現(xiàn)它并沒(méi)有這樣一個(gè)自有方法抵蚊,那么它就嘗試讀 __proto__ 上的方法魂务,發(fā)現(xiàn) __proto__ 屬性(也即 base 數(shù)組)上有這樣一個(gè)自有方法曼验,那么它就不必再向上搜索而直接使用 base.push
通過(guò)這種方式粘姜,我們不必為每一個(gè)數(shù)組重寫一遍 push 方法,也不必去修改 Array.prototype 熔酷,看起來(lái)倒像是一個(gè)兩全其美的方法孤紧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拒秘,隨后出現(xiàn)的幾起案子号显,更是在濱河造成了極大的恐慌,老刑警劉巖躺酒,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件押蚤,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡羹应,警方通過(guò)查閱死者的電腦和手機(jī)揽碘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)园匹,“玉大人雳刺,你說(shuō)我怎么就攤上這事÷阄ィ” “怎么了掖桦?”我有些...
    開(kāi)封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)供汛。 經(jīng)常有香客問(wèn)我枪汪,道長(zhǎng),這世上最難降的妖魔是什么怔昨? 我笑而不...
    開(kāi)封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任雀久,我火速辦了婚禮,結(jié)果婚禮上朱监,老公的妹妹穿的比我還像新娘岸啡。我一直安慰自己,他們只是感情好赫编,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布巡蘸。 她就那樣靜靜地躺著,像睡著了一般擂送。 火紅的嫁衣襯著肌膚如雪悦荒。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天嘹吨,我揣著相機(jī)與錄音搬味,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碰纬,可吹牛的內(nèi)容都是我干的萍聊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼悦析,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寿桨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起强戴,我...
    開(kāi)封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤亭螟,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后骑歹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體预烙,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年道媚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扁掸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衰琐,死狀恐怖也糊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情羡宙,我是刑警寧澤狸剃,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站狗热,受9級(jí)特大地震影響钞馁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匿刮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一僧凰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧熟丸,春花似錦训措、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至纱兑,卻和暖如春呀闻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背潜慎。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工捡多, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蓖康,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓垒手,卻偏偏與公主長(zhǎng)得像蒜焊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子科贬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • Vue 實(shí)例 屬性和方法 每個(gè) Vue 實(shí)例都會(huì)代理其 data 對(duì)象里所有的屬性:var data = { a:...
    云之外閱讀 2,204評(píng)論 0 6
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容山涡,還有我對(duì)于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,046評(píng)論 0 29
  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,216評(píng)論 0 4
  • bower install jquery 在項(xiàng)目目錄下安裝jquer bower使用入門 jingyan.baid...
    如果你還記得我是小雙魚閱讀 346評(píng)論 0 0
  • 無(wú)窮往事留詩(shī)夢(mèng)唆迁,多少歡娛到酒杯。 但愿常將歲華惜竞穷,不須空使寸心哀唐责。 隨時(shí)入韻唱酬誦,每日出門歸去來(lái)瘾带。 可嘆十分奇俊...
    雪窗_武立之閱讀 128評(píng)論 0 2