vue.js - v-bind 的一些理解和思考

一、v-bind 初探

它是一個(gè) vue 指令,用于綁定 html 屬性,如下:

<div id="app">
    <p v-bind:title="title">html屬性不能使用雙大括號(hào)形式綁定谈为,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
    el: '#app',
    data: {
        title: 'title content'
    }
});

這里的 html 最后會(huì)渲染成:

<div id="app">
    <p title="title content">html屬性不能使用雙大括號(hào)形式綁定,只能使用v-bind指令</p>
</div>

二踢关、指令預(yù)期值

上面這種 v-bind 這也是我們對(duì)于 vue 指令最初的理解伞鲫,但實(shí)際上,vue 指令的預(yù)期值(如 v-bind:class="classProperty" 中签舞,v-bind 是指令秕脓,: 后面的 class 是參數(shù),而 classProperty 則在官方文檔中被稱為“預(yù)期值”)儒搭,除了像上面那樣綁定一個(gè)字符串類型變量吠架,其實(shí)它是支持一個(gè)單一 JavaScript 表達(dá)式v-for 除外)。
所以在這里师妙,我們就可以有更多的選擇诵肛,例如:

(1)執(zhí)行運(yùn)算

<div id="app">
    <p v-bind:title="t1 + ' ' + t2">html屬性不能使用雙大括號(hào)形式綁定,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
    el: '#app',
    data: {
        t1: 'title1',
        t2: 'title2'
    }
});

最后渲染的結(jié)果:

<div id="app">
    <p title="title1 title2">html屬性不能使用雙大括號(hào)形式綁定默穴,只能使用v-bind指令</p>
</div>

(2)執(zhí)行函數(shù)等

<div id="app">
    <p v-bind:title="getTitle()">html屬性不能使用雙大括號(hào)形式綁定怔檩,只能使用v-bind指令</p>
</div>
......
var vm = new Vue({
    el: '#app',
    data: {
        getTitle: function () {
            return 'title content';
        }
    }
});

最后渲染的結(jié)果:

<div id="app">
    <p title="title content">html屬性不能使用雙大括號(hào)形式綁定,只能使用v-bind指令</p>
</div>

三蓄诽、支持的數(shù)據(jù)類型

上面的內(nèi)容薛训,指令預(yù)期值得到的都是字符串類型的數(shù)據(jù),但實(shí)際上仑氛,我們知道 js 有很多數(shù)據(jù)類型乙埃,它如果放入其中呢?

(1)對(duì)象類型

<div id="app">
    <p v-bind:title="obj">content</p>
</div>
......
var obj = {};
var vm = new Vue({
    el: '#app',
    data: {
        obj: obj
    }
});

為什么一來(lái)就選擇對(duì)象類型呢锯岖?答案是它比較有代表性介袜,它渲染結(jié)果如下:

<div id="app">
    <p title="[object Object]">content</p>
</div>

誒,這個(gè)怎么有點(diǎn)眼熟出吹?有點(diǎn)像...沒錯(cuò)遇伞!對(duì)象的 toString 方法的返回值!為了驗(yàn)證我們的猜想捶牢,我們進(jìn)行進(jìn)一步的測(cè)試:

<div id="app">
    <p v-bind:title="obj">content</p>
</div>
......
var obj = {};

obj.toString = function () {
    return 'edited in toString!';
};

var vm = new Vue({
    el: '#app',
    data: {
        obj: obj
    }
});

上面這里修改了 objtoString 方法(但準(zhǔn)確的說(shuō)鸠珠,這里不是修改,而是添加秋麸。一開始的 obj 對(duì)象上自身是沒有 toString 方法的渐排,它繼承了 Object.prototype.toString,但這里我們執(zhí)行 obj.toString = function..... 實(shí)際上是為它添加了一個(gè) toString 方法灸蟆,使得它執(zhí)行的時(shí)候驯耻,不用再去調(diào)用繼承自 Object 的方法),渲染結(jié)果如下:

<div id="app">
    <p title="edited in toString!">content</p>
</div>

這里就進(jìn)一步證實(shí)了我們的猜想。

(2)數(shù)組類型

數(shù)組類型的 toString 方法和對(duì)象類型的有所不同可缚,它將返回和執(zhí)行 arr.join(',') 相同的結(jié)果孽水。如 [1, 2, 3].toString() 將返回 “1,2,3”。下面進(jìn)行測(cè)試:

<div id="app">
    <p v-bind:title="arr">content</p>
</div>
......
var vm = new Vue({
    el: '#app',
    data: {
        arr: [1, 2, 3]
    }
});

渲染結(jié)果如下:

<div id="app">
    <p title="1,2,3">content</p>
</div>

仍然跟預(yù)期結(jié)果一樣城看。

(3)其它類型

  • number 類型,正常執(zhí)行 toString杏慰,包括數(shù)字0测柠,結(jié)果都正常渲染成對(duì)應(yīng)的字符串;
  • boolean 類型缘滥,true 正常渲染成字符串 "true"轰胁,但 false 雖然執(zhí)行 toString 方法將返回 "false" 字符串,但是卻沒有渲染出來(lái)朝扼;
  • null / undefined 類型赃阀,二者沒有 toString 方法,也沒有渲染出來(lái)擎颖。
    顯然榛斯,在執(zhí)行 toString 方法之前,vue 內(nèi)部應(yīng)該先做了類型校驗(yàn)搂捧,滿足條件才輸出驮俗。而且這里不是簡(jiǎn)單的真 / 假值校驗(yàn),因?yàn)?允跑、0 雖為假值王凑,但最終卻像真值一樣渲染了出來(lái)。具體如何實(shí)現(xiàn)聋丝,可能需要參考 vue 的源碼了索烹,這里不再深究。

四弱睦、多 html 屬性值綁定

一個(gè)的 html 屬性值百姓,可能包含許多內(nèi)容,需要我們進(jìn)行一些操作每篷,將多個(gè)數(shù)據(jù)綁定到一個(gè)屬性上瓣戚,這里我們可以考慮像前面一樣,通過(guò)如 “+” 等運(yùn)算符號(hào)等實(shí)現(xiàn)字符串的連接操作焦读。但是事實(shí)上子库,字符串連接麻煩又易錯(cuò),不易于維護(hù)矗晃。于是我們可以考慮像前面一樣向指令預(yù)期值中存入一個(gè)對(duì)象或數(shù)組仑嗅,來(lái)實(shí)現(xiàn)多個(gè)數(shù)據(jù)綁定到一個(gè)屬性上的作用。

(1)利用對(duì)象綁定

<div id="app">
    <p v-bind:title="obj">content</p>
</div>
......
var obj = {
    name: 'Dale',
    age: 22
};

// 利用 for-in 循環(huán)遍歷對(duì)象屬性,拼接成字符串
obj.toString = function () {
    var str = '';
    for(var i in this) {
        str += i + ': ' + this[i] + '; ';
    }
    return str;
};

// 防止 toString 方法自身被遍歷出來(lái)
Object.defineProperty(obj, 'toString', {'enumerable': false});

var vm = new Vue({
    el: '#app',
    data: {
        obj: obj
    }
});

輸出結(jié)果:

<div id="app">
    <p title="name: Dale; age: 22; ">content</p>
</div>

上面通過(guò) for-in 循環(huán)在 toString 方法中得到所有可遍歷的屬性以及對(duì)應(yīng)的屬性值仓技,然后將其拼接成字符串再進(jìn)行輸出鸵贬,可以實(shí)現(xiàn)多屬性值綁定,至于如何拼接脖捻,可以自己在 toString 方法中進(jìn)行不同的實(shí)現(xiàn) 阔逼。

(2)利用數(shù)組綁定

<div id="app">
    <p v-bind:title="arr">content</p>
</div>
......
var arr = [1, 2, 3];

arr.toString = function () {
    return this.join(' ');
};

var vm = new Vue({
    el: '#app',
    data: {
        arr: arr
    }
});

渲染結(jié)果如下:

<div id="app">
    <p title="1 2 3">content</p>
</div>

相比于對(duì)象字符串拼接,數(shù)組的拼接操作則顯得簡(jiǎn)單得多地沮,可以直接在 toString 方法返回 join 方法的返回值嗜浮,默認(rèn)的 toString 方法的返回值其實(shí)就和 join(',') 的返回值相同。

(3)思考

其實(shí)想想一個(gè) html 屬性綁定多個(gè)值的情況其實(shí)并不少見摩疑,最典型的應(yīng)該是 classstyle 屬性危融,或者說(shuō)我們經(jīng)常都會(huì)接觸到這樣的場(chǎng)景。
但我們這里的實(shí)現(xiàn)雷袋,看起來(lái)還是問(wèn)題比較多吉殃,數(shù)組的綁定還好,對(duì)象的綁定楷怒,除了每次要重寫 toString 方法以外蛋勺,我們還需要設(shè)置 toString 方法變得不可枚舉,否則它將在 for-in 循環(huán)中被遍歷出來(lái)(一般情況下率寡,這不是我們希望看到的結(jié)果)迫卢,這樣無(wú)疑會(huì)增加很多重復(fù)性工作,而 vue 為我們考慮到了這一點(diǎn)冶共,它在框架內(nèi)部進(jìn)行了一些優(yōu)化操作乾蛤。

五、vue 對(duì)于 classstyle 綁定的增強(qiáng)

基于上面的情況捅僵,vue 對(duì) classstyle 這兩個(gè) html 屬性進(jìn)行了一定程度的增強(qiáng)家卖。vue 具體的實(shí)現(xiàn)方式請(qǐng)參考其源碼,這里僅給出基于上面的結(jié)論的實(shí)現(xiàn)方式庙楚。

(1)基于對(duì)象針對(duì) class 的增強(qiáng)

<div id="app">
    <p v-bind:class="obj">content</p>
</div>
......
var obj = {
    c1: true,
    c2: false,
    c3: null,
    c4: undefined
};

obj.toString = function () {
    var str = '';
    for(var i in this) {
        if(this[i]) {
            str += i + ' ';
        }
    }

    return str;
};

// 防止 toString 方法自身被遍歷出來(lái)
Object.defineProperty(obj, 'toString', {'enumerable': false});

var vm = new Vue({
    el: '#app',
    data: {
        obj: obj
    }
});

渲染結(jié)果:

<div id="app">
    <p class="c1">content</p>
</div>

同樣是 for-in上荡,與之前不同的是,當(dāng)檢測(cè)到 obj 的某個(gè)屬性值為真的時(shí)候馒闷,則將這個(gè)屬性的屬性名添加到綁定的元素的 class 上酪捡。當(dāng)然,我這里只是一個(gè)模擬實(shí)現(xiàn)纳账,vue 實(shí)際的實(shí)現(xiàn)方式逛薇,請(qǐng)參考 vue 源碼。

(2)基于數(shù)組對(duì) class 的增強(qiáng)

<div id="app">
    <p v-bind:class="arr">content</p>
</div>
.......
var arr = ['c1', 'c2', 'c3'];

arr.toString = function () {
    return this.join(' ');
};

var vm = new Vue({
    el: '#app',
    data: {
        arr: arr
    }
});

渲染結(jié)果:

<div id="app">
    <p class="c1 c2 c3">content</p>
</div>

這里基本和前面的實(shí)現(xiàn)思路一樣疏虫,利用 join(' ') 實(shí)現(xiàn)永罚。

(3)基于對(duì)象對(duì) style 的增強(qiáng)

<div id="app">
    <p v-bind:style="obj">content</p>
</div>
......
var obj = {
    color: 'red',
    backgroundColor: '#ddd',
    fontSize: '20px',
};

obj.toString = function () {
    var str = '';
    for(var i in this) {
        if(this[i]) {
            str += i + ':' + this[i] + ';';
        }
    }

    return str;
};

// 防止 toString 方法自身被遍歷出來(lái)
Object.defineProperty(obj, 'toString', {'enumerable': false});

var vm = new Vue({
    el: '#app',
    data: {
        obj: obj
    }
});

渲染結(jié)果:

<div id="app">
    <p style="color: red; background-color: rgb(221, 221, 221); font-size: 20px;">content</p>
</div>

這里基本和前面的實(shí)現(xiàn)思路一樣啤呼,利用 for-in 配合字符串拼接實(shí)現(xiàn)。
(4)基于數(shù)組對(duì) style 的增強(qiáng)

<div id="app">
    <p v-bind:style="arr">content</p>
</div>

<script>
var arr = [{
        color: "red"
    }, {
        backgroundColor: '#ddd'
    }, {
        fontSize: '20px'
    }];

arr.toString = function () {
    var str = '';
    arr.forEach(function (val, key) {
        for(var i in val) {
            str += i + ':' + val[i] + ';';
        }
    });
};

var vm = new Vue({
    el: '#app',
    data: {
        arr: arr
    }
});

渲染結(jié)果:

<div id="app">
    <p style="color: red; background-color: rgb(221, 221, 221); font-size: 20px;">content</p>
</div>

這里通過(guò) forEach 方法遍歷了數(shù)組呢袱,然后將數(shù)組元素(也就是這里我們的樣式對(duì)象)再通過(guò) for-in 遍歷并拼接成樣式字符串達(dá)到效果官扣。

六、結(jié)語(yǔ)

再次強(qiáng)調(diào)羞福,這里只是個(gè)人的理解和思考惕蹄,僅供參考,vue 本身的實(shí)現(xiàn)方式未必相同治专,如果有需要焊唬,請(qǐng)參考 vue 源碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末看靠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子液肌,更是在濱河造成了極大的恐慌挟炬,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗦哆,死亡現(xiàn)場(chǎng)離奇詭異谤祖,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)老速,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門粥喜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人橘券,你說(shuō)我怎么就攤上這事额湘。” “怎么了旁舰?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵锋华,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我箭窜,道長(zhǎng)毯焕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任磺樱,我火速辦了婚禮纳猫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘竹捉。我一直安慰自己芜辕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布活孩。 她就那樣靜靜地躺著物遇,像睡著了一般乖仇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上询兴,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天乃沙,我揣著相機(jī)與錄音,去河邊找鬼诗舰。 笑死警儒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的眶根。 我是一名探鬼主播蜀铲,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼属百!你這毒婦竟也來(lái)了记劝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤族扰,失蹤者是張志新(化名)和其女友劉穎厌丑,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渔呵,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怒竿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扩氢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耕驰。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖录豺,靈堂內(nèi)的尸體忽然破棺而出朦肘,到底是詐尸還是另有隱情,我是刑警寧澤双饥,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布厚骗,位于F島的核電站,受9級(jí)特大地震影響兢哭,放射性物質(zhì)發(fā)生泄漏领舰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一迟螺、第九天 我趴在偏房一處隱蔽的房頂上張望冲秽。 院中可真熱鬧,春花似錦矩父、人聲如沸锉桑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)民轴。三九已至攻柠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間后裸,已是汗流浹背瑰钮。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留微驶,地道東北人浪谴。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像因苹,于是被迫代替她去往敵國(guó)和親苟耻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理扶檐,服務(wù)發(fā)現(xiàn)凶杖,斷路器,智...
    卡卡羅2017閱讀 134,672評(píng)論 18 139
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容款筑,還有我對(duì)于 Vue 1.0 印象不深的內(nèi)容官卡。關(guān)于...
    云之外閱讀 5,050評(píng)論 0 29
  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,237評(píng)論 0 4
  • 追星 原創(chuàng)文 | 是熱河 (清風(fēng)浪港手寫鋪原創(chuàng)文颈嚼,未經(jīng)授權(quán)請(qǐng)勿轉(zhuǎn)載) “如果這是我第一次見到你我肯的也會(huì)嚎啕大哭,...
    清風(fēng)浪港手寫鋪閱讀 386評(píng)論 0 0
  • 這一段時(shí)間呆在天津饭寺,下午沒什么事做阻课,挺無(wú)聊的,看了看艰匙,百度地圖限煞,附近有個(gè)李叔同紀(jì)念館,頓時(shí)耳邊就響起了那個(gè)熟悉的旋...
    Anna夢(mèng)非夢(mèng)閱讀 498評(píng)論 7 6