JavaScript的Vue.js庫入門學(xué)習(xí)教程
Vue是一個(gè)小巧輕便的javascript庫。它有一個(gè)簡單易懂的API,能夠讓開發(fā)者在開發(fā)web應(yīng)用的時(shí)候更加簡易便捷。實(shí)際上,一直讓Vue引以為豪的是它的便捷性、執(zhí)行力、靈活性。
這篇教程的目的就是通過一些例子,讓你能夠概覽一些基本的概念和特性。在接下來的其他教程里,你會(huì)學(xué)到Vue更多的有用的特性,從而用Vue搭建一個(gè)可擴(kuò)展的項(xiàng)目。
MVVM 數(shù)據(jù)綁定
MVVM的本質(zhì)是通過數(shù)據(jù)綁定鏈接View和Model,讓數(shù)據(jù)的變化自動(dòng)映射為視圖的更新。Vue.js在數(shù)據(jù)綁定的API設(shè)計(jì)上借鑒了Angular的指令機(jī)制:用戶可以通過具有特殊前綴的HTML 屬性來實(shí)現(xiàn)數(shù)據(jù)綁定,也可以使用常見的花括號(hào)模板插值,或是在表單元素上使用雙向綁定:
<!-- 指令 -->
<span v-text="msg"></span>
<!-- 插值 -->
<span>{{msg}}</span>
<!-- 雙向綁定 -->
<input v-model="msg">
插值本質(zhì)上也是指令,只是為了方便模板的書寫。在模板的編譯過程中,Vue.js會(huì)為每一處需要?jiǎng)討B(tài)更新的DOM節(jié)點(diǎn)創(chuàng)建一個(gè)指令對象。每當(dāng)一個(gè)指令對象觀測的數(shù)據(jù)變化時(shí),它便會(huì)對所綁定的目標(biāo)節(jié)點(diǎn)執(zhí)行相應(yīng)的DOM操作。基于指令的數(shù)據(jù)綁定使得具體的DOM操作都被合理地封裝在指令定義中,業(yè)務(wù)代碼只需要涉及模板和對數(shù)據(jù)狀態(tài)的操作即可,這使得應(yīng)用的開發(fā)效率和可維護(hù)性都大大提升。

與Angular不同的是,Vue.js的API里并沒有繁雜的module、controller、scope、factory、service等概念,一切都是以“ViewModel 實(shí)例”為基本單位:
<!-- 模板 -->
<div id="app">
{{msg}}
</div>
// 原生對象即數(shù)據(jù)
var data = {
msg: 'hello!'
}
// 創(chuàng)建一個(gè) ViewModel 實(shí)例
var vm = new Vue({
// 選擇目標(biāo)元素
el: '#app',
// 提供初始數(shù)據(jù)
data: data
})
渲染結(jié)果:
<div id="app"> hello! </div>
在渲染的同時(shí),Vue.js也已經(jīng)完成了數(shù)據(jù)的動(dòng)態(tài)綁定:此時(shí)如果改動(dòng)data.msg的值,DOM將自動(dòng)更新。是不是非常簡單易懂呢?除此之外,Vue.js對自定義指令、過濾器的API也做了大幅的簡化,如果你有Angular的開發(fā)經(jīng)驗(yàn),上手會(huì)非常迅速。
數(shù)據(jù)觀測的實(shí)現(xiàn)
Vue.js的數(shù)據(jù)觀測實(shí)現(xiàn)原理和Angular有著本質(zhì)的不同。了解Angular的讀者可能知道,Angular的數(shù)據(jù)觀測采用的是臟檢查(dirty checking)機(jī)制。每一個(gè)指令都會(huì)有一個(gè)對應(yīng)的用來觀測數(shù)據(jù)的對象,叫做watcher;一個(gè)作用域中會(huì)有很多個(gè)watcher。每當(dāng)界面需要更新時(shí),Angular會(huì)遍歷當(dāng)前作用域里的所有watcher,對它們一一求值,然后和之前保存的舊值進(jìn)行比較。如果求值的結(jié)果變化了,就觸發(fā)對應(yīng)的更新,這個(gè)過程叫做digest cycle。臟檢查有兩個(gè)問題:
任何數(shù)據(jù)變動(dòng)都意味著當(dāng)前作用域的每一個(gè)watcher需要被重新求值,因此當(dāng)watcher的數(shù)量龐大時(shí),應(yīng)用的性能就不可避免地受到影響,并且很難優(yōu)化。
當(dāng)數(shù)據(jù)變動(dòng)時(shí),框架并不能主動(dòng)偵測到變化的發(fā)生,需要手動(dòng)觸發(fā)digest cycle才能觸發(fā)相應(yīng)的DOM 更新。Angular通過在DOM事件處理函數(shù)中自動(dòng)觸發(fā)digest cycle部分規(guī)避了這個(gè)問題,但還是有很多情況需要用戶手動(dòng)進(jìn)行觸發(fā)。
Vue.js采用的則是基于依賴收集的觀測機(jī)制。從原理上來說,和老牌MVVM框架Knockout是一樣的。依賴收集的基本原理是:
將原生的數(shù)據(jù)改造成 “可觀察對象”。一個(gè)可觀察對象可以被取值,也可以被賦值。
在watcher的求值過程中,每一個(gè)被取值的可觀察對象都會(huì)將當(dāng)前的watcher注冊為自己的一個(gè)訂閱者,并成為當(dāng)前watcher的一個(gè)依賴。
當(dāng)一個(gè)被依賴的可觀察對象被賦值時(shí),它會(huì)通知所有訂閱自己的watcher重新求值,并觸發(fā)相應(yīng)的更新。
依賴收集的優(yōu)點(diǎn)在于可以精確、主動(dòng)地追蹤數(shù)據(jù)的變化,不存在上述提到的臟檢查的兩個(gè)問題。但傳統(tǒng)的依賴收集實(shí)現(xiàn),比如Knockout,通常需要包裹原生數(shù)據(jù)來制造可觀察對象,在取值和賦值時(shí)需要采用函數(shù)調(diào)用的形式,在進(jìn)行數(shù)據(jù)操作時(shí)寫法繁瑣,不夠直觀;同時(shí),對復(fù)雜嵌套結(jié)構(gòu)的對象支持也不理想。
Vue.js利用了ES5的Object.defineProperty方法,直接將原生數(shù)據(jù)對象的屬性改造為getter和setter,在這兩個(gè)函數(shù)內(nèi)部實(shí)現(xiàn)依賴的收集和觸發(fā),而且完美支持嵌套的對象結(jié)構(gòu)。對于數(shù)組,則通過包裹數(shù)組的可變方法(比如push)來監(jiān)聽數(shù)組的變化。這使得操作Vue.js的數(shù)據(jù)和操作原生對象幾乎沒有差別[注:在添加/刪除屬性,或是修改數(shù)組特定位置元素時(shí),需要調(diào)用特定的函數(shù),如obj.$add(key, value)才能觸發(fā)更新。這是受ES5的語言特性所限。],數(shù)據(jù)操作的邏輯更為清晰流暢,和第三方數(shù)據(jù)同步方案的整合也更為方便。

組件系統(tǒng)
在大型的應(yīng)用中,為了分工、復(fù)用和可維護(hù)性,我們不可避免地需要將應(yīng)用抽象為多個(gè)相對獨(dú)立的模塊。在較為傳統(tǒng)的開發(fā)模式中,我們只有在考慮復(fù)用時(shí)才會(huì)將某一部分做成組件;但實(shí)際上,應(yīng)用類 UI 完全可以看作是全部由組件樹構(gòu)成的:

因此,在Vue.js的設(shè)計(jì)中將組件作為一個(gè)核心概念??梢哉f,每一個(gè)Vue.js應(yīng)用都是圍繞著組件來開發(fā)的。
注冊一個(gè)Vue.js組件十分簡單:
Vue.component('my-component', {
// 模板
template: '<div>{{msg}} {{privateMsg}}</div>',
// 接受參數(shù)
props: {
msg: String<br>
},
// 私有數(shù)據(jù),需要在函數(shù)中返回以避免多個(gè)實(shí)例共享一個(gè)對象
data: function () {
return {
privateMsg: 'component!'
}
}
})
注冊之后即可在父組件模板中以自定義元素的形式調(diào)用一個(gè)子組件:
<my-component msg="hello"></my-component>
渲染結(jié)果:
<div>hello component!</div>
Vue.js的組件可以理解為預(yù)先定義好了行為的ViewModel類。一個(gè)組件可以預(yù)定義很多選項(xiàng),但最核心的是以下幾個(gè):
- 模板(template):模板聲明了數(shù)據(jù)和最終展現(xiàn)給用戶的DOM之間的映射關(guān)系。
- 初始數(shù)據(jù)(data):一個(gè)組件的初始數(shù)據(jù)狀態(tài)。對于可復(fù)用的組件來說,這通常是私有的狀態(tài)。
- 接受的外部參數(shù)(props):組件之間通過參數(shù)來進(jìn)行數(shù)據(jù)的傳遞和共享。參數(shù)默認(rèn)是單向綁定(由上至下),但也可以顯式地聲明為雙向綁定。
- 方法(methods):對數(shù)據(jù)的改動(dòng)操作一般都在組件的方法內(nèi)進(jìn)行??梢酝ㄟ^v-on指令將用戶輸入事件和組件方法進(jìn)行綁定。
- 生命周期鉤子函數(shù)(lifecycle hooks):一個(gè)組件會(huì)觸發(fā)多個(gè)生命周期鉤子函數(shù),比如created,attached,destroyed等等。在這些鉤子函數(shù)中,我們可以封裝一些自定義的邏輯。和傳統(tǒng)的MVC相比,可以理解為 Controller的邏輯被分散到了這些鉤子函數(shù)中。
- 私有資源(assets):Vue.js當(dāng)中將用戶自定義的指令、過濾器、組件等統(tǒng)稱為資源。由于全局注冊資源容易導(dǎo)致命名沖突,一個(gè)組件可以聲明自己的私有資源。私有資源只有該組件和它的子組件可以調(diào)用。
- 除此之外,同一顆組件樹之內(nèi)的組件之間還可以通過內(nèi)建的事件API來進(jìn)行通信。Vue.js提供了完善的定義、復(fù)用和嵌套組件的API,讓開發(fā)者可以像搭積木一樣用組件拼出整個(gè)應(yīng)用的界面。這個(gè)思路的可行性在Facebook開源的React當(dāng)中也得到了印證。
基于構(gòu)建工具的單文件組件格式
Vue.js的核心庫只提供基本的API,本身在如何組織應(yīng)用的文件結(jié)構(gòu)上并不做太多約束。但在構(gòu)建大型應(yīng)用時(shí),推薦使用Webpack+vue-loader這個(gè)組合以使針對組件的開發(fā)更高效。
Webpack是由Tobias Koppers開發(fā)的一個(gè)開源前端模塊構(gòu)建工具。它的基本功能是將以模塊格式書寫的多個(gè)JavaScript文件打包成一個(gè)文件,同時(shí)支持CommonJS和AMD格式。但讓它與眾不同的是,它提供了強(qiáng)大的loader API來定義對不同文件格式的預(yù)處理邏輯,從而讓我們可以將CSS、模板,甚至是自定義的文件格式當(dāng)做JavaScript模塊來使用。Webpack 基于loader還可以實(shí)現(xiàn)大量高級(jí)功能,比如自動(dòng)分塊打包并按需加載、對圖片資源引用的自動(dòng)定位、根據(jù)圖片大小決定是否用base64內(nèi)聯(lián)、開發(fā)時(shí)的模塊熱替換等等,可以說是目前前端構(gòu)建領(lǐng)域最有競爭力的解決方案之一。
我在Webpack的loader API基礎(chǔ)上開發(fā)了vue-loader插件,從而讓我們可以用這樣的單文件格式 (*.vue) 來書寫Vue組件:
<style>
.my-component h2 {
color: red;
}
</style>
<template>
<div class="my-component">
<h2>Hello from {{msg}}</h2>
<other-component></other-component>
</div>
</template>
<script>
// 遵循 CommonJS 模塊格式
var otherComponent = require('./other-component')
// 導(dǎo)出組件定義
module.exports = {
data: function () {
return {
msg: 'vue-loader'
}
},
components: {
'other-component': otherComponent
}
}
</script>
同時(shí),還可以在*.vue文件中使用其他預(yù)處理器,只需要安裝對應(yīng)的Webpack loader即可:
<style lang="stylus">
.my-component h2
color red
</style>
<template lang="jade">
div.my-component
h2 Hello from {{msg}}
</template>
<script lang="babel">
// 利用 Babel 編譯 ES2015
export default {
data () {
return {
msg: 'Hello from Babel!'
}
}
}
</script>
這樣的組件格式,把一個(gè)組件的模板、樣式、邏輯三要素整合在同一個(gè)文件中,即方便開發(fā),也方便復(fù)用和維護(hù)。另外,Vue.js本身支持對組件的異步加載,配合Webpack的分塊打包功能,可以極其輕松地實(shí)現(xiàn)組件的異步按需加載。
其他特性
Vue.js還有幾個(gè)值得一提的特性:
- 異步批量DOM更新:當(dāng)大量數(shù)據(jù)變動(dòng)時(shí),所有受到影響的watcher會(huì)被推送到一個(gè)隊(duì)列中,并且每個(gè)watcher只會(huì)推進(jìn)隊(duì)列一次。這個(gè)隊(duì)列會(huì)在進(jìn)程的下一個(gè) “tick” 異步執(zhí)行。這個(gè)機(jī)制可以避免同一個(gè)數(shù)據(jù)多次變動(dòng)產(chǎn)生的多余DOM操作,也可以保證所有的DOM寫操作在一起執(zhí)行,避免DOM讀寫切換可能導(dǎo)致的layout。
- 動(dòng)畫系統(tǒng):Vue.js提供了簡單卻強(qiáng)大的動(dòng)畫系統(tǒng),當(dāng)一個(gè)元素的可見性變化時(shí),用戶不僅可以很簡單地定義對應(yīng)的CSS Transition或Animation效果,還可以利用豐富的JavaScript鉤子函數(shù)進(jìn)行更底層的動(dòng)畫處理。
- 可擴(kuò)展性:除了自定義指令、過濾器和組件,Vue.js還提供了靈活的mixin機(jī)制,讓用戶可以在多個(gè)組件中復(fù)用共同的特性。
利用new Vue()創(chuàng)建一個(gè)Vue實(shí)例
我們可以先初始化一個(gè)html頁面,然后我們需要引入Vue 的 JS 文件。引入的方式有很多,我們可以在script中引入Vue的cdn,或者去官網(wǎng)上下載Vue的min.js,或者用 npm 安裝一個(gè)Vue的依賴。方便起見,本文中就用cdn引入。
<!DOCTYPE html>
<html>
<head>
<title>從零開始學(xué)Vue</title>
</head>
<body>
<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
</body>
</html>
當(dāng)你在開發(fā)過程中,確保你使用的是沒有壓縮過的版本,因?yàn)闆]有壓縮的版本會(huì)提供有用的詳細(xì)的警告,將會(huì)給你的代碼書寫節(jié)省很多時(shí)間。
我們先在body里面寫入一個(gè)div,并且創(chuàng)建一個(gè)Vue實(shí)例,然后將實(shí)例和div綁定起來。
當(dāng)你創(chuàng)建一個(gè)新的Vue實(shí)例的時(shí)候要使用Vue()構(gòu)造器,然后在你的實(shí)例中指出你的掛載點(diǎn)。這個(gè)掛載點(diǎn)就是你想要?jiǎng)澐殖鰜淼腣ue實(shí)例的邊界。掛載點(diǎn)和實(shí)例邊界是一一對應(yīng)的,你只能在掛載點(diǎn)上處理你實(shí)例邊界內(nèi)的事務(wù),而不能在你的掛載點(diǎn)上處理實(shí)例邊界外的事務(wù)。
在Vue實(shí)例中設(shè)置掛載點(diǎn)的參數(shù)是 “ el ”,el 的值可以用dom元素定義。
<!DOCTYPE html>
<html>
<head>
<title>從零開始學(xué)Vue</title>
</head>
<body>
<div id="vueInstance">這中間就是實(shí)例掛載點(diǎn)的實(shí)例邊界</div>
<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>
<script>
// 創(chuàng)建一個(gè)新的Vue實(shí)例,并設(shè)置掛載點(diǎn)
var V = new Vue({
el : '#vueInstance'
});
</script>
</body>
</html>
就像你在上面看到的那樣,new一個(gè)Vue()就能創(chuàng)建一個(gè)新的實(shí)例,然后指定一個(gè)DOM元素作為實(shí)例的掛載點(diǎn)。定義掛載點(diǎn)的時(shí)候,我們用到了css選擇器的id來定義。實(shí)例化的名字也可以自己來定義,以便之后調(diào)用。
利用v-model進(jìn)行雙向數(shù)據(jù)綁定
我們可以用v-model對input輸入框進(jìn)行綁定,從而我們可以使用動(dòng)態(tài)的獲取數(shù)據(jù)對象的值。你可以認(rèn)為v-model是一個(gè)指定的屬性,就像html元素的屬性。這里的雙向數(shù)據(jù)綁定可以用在很多表單元素上,比如input、textarea、select。
Vue利用v-model這個(gè)指令綁定了一個(gè)數(shù)據(jù),而這個(gè)數(shù)據(jù)是我們希望能夠通過用戶輸入操作而更新的數(shù)據(jù)。
比如我們下面這個(gè)例子,我們要在input標(biāo)簽上綁定數(shù)據(jù)name,我們需要在Vue實(shí)例中的data對象中實(shí)現(xiàn)聲明。
<div id="vueInstance"> 輸入您的姓名: <input type="text" v-model="name"> </div>
<script src="http://cdn.jsdelivr.net/vue/1.0.16/vue.js"></script>//之后這行會(huì)省略
<script>
var V = new Vue({
el : '#vueInstance',
data : {
name : '_Appian'
}
});
</script>
無論用戶輸入多少次,這個(gè)name都會(huì)被自動(dòng)更新。并且,如果name的值被改變了,其他有映射name的地方的值也會(huì)被修改。
這種input框和映射的同步修改的原因,就是利用v-model這個(gè)指令,讓數(shù)據(jù)通過底層的數(shù)據(jù)流進(jìn)行綁定后直接修改。這就是數(shù)據(jù)的雙向綁定的概念。
為了證明這個(gè)概念,我們可以利用$data打印出數(shù)據(jù)的映射來看看。
<div id="vueInstance">
輸入您的姓名: <input type="text" v-model="name">
<p>{{ $data | json }}</p> //#1
<p>{{ name }}</p> //#2
</div>
<script>
var V = new Vue({
el : '#vueInstance',
data : {
name : '_Appian'
}
});
</script>
其1:
$data是Vue實(shí)例觀察的數(shù)據(jù)對象,本質(zhì)類型是一個(gè)對象,所以可以轉(zhuǎn)成JSON??梢杂靡粋€(gè)新的對象替換。實(shí)例代理了它的數(shù)據(jù)對象的屬性。
{{}},利用兩個(gè)花括號(hào)進(jìn)行插值。這里插入的值是$data實(shí)時(shí)變化的值。
| json,只是一個(gè)更直觀的能讓數(shù)據(jù)展示出來的方法。也可以看做是一個(gè)過濾器,就像JSON.stringify()的效果一樣。
其2:
{{ name }},就是直接在插值表達(dá)式,兩個(gè)花括號(hào)中間插入數(shù)據(jù)變量,直接映射name的值。
Vue就是這么簡單的進(jìn)行數(shù)據(jù)的雙向綁定,只需要一個(gè)v-model指令就可以,而不需要利用js或者jq來控制數(shù)據(jù)。相信你能從上面的例子中理清邏輯。
利用v-on進(jìn)行事件綁定
Vue是利用v-on指令進(jìn)行事件監(jiān)聽和事件分發(fā)的。你可以在Vue的實(shí)例中創(chuàng)建一個(gè)方法來綁定監(jiān)聽事件,可以創(chuàng)建一個(gè)方法來分派一個(gè)點(diǎn)擊事件。
下面的例子中,我們將創(chuàng)建一個(gè)say方法,這個(gè)方法綁定在一個(gè)button上。點(diǎn)擊產(chǎn)生的效果就是彈出一個(gè)帶有用戶name的歡迎框。為了將這個(gè)方法指派給button,我們需要用v-on:click來進(jìn)行事件綁定。
<div id="vueInstance"> 輸入您的姓名: <input type="text" v-model="name"> <button v-on:click="say">歡迎點(diǎn)擊</button> //#1 <button @click="say">歡迎點(diǎn)擊</button> //#2 </div>
<script>
var V = new Vue({
el : '#vueInstance',
data : {
name : '_Appian'
},
methods : {
say : function(){
alert('歡迎' + this.name);
}
}
});
</script>
當(dāng)然了,不僅是可以綁定click點(diǎn)擊事件,還可以綁定其他鼠標(biāo)事件,鍵盤輸入事件等一些js的事件類型。比如v-on:mouseover,v-on:keydown, v-on:submit, v-on:keypress,v-on:keyup.13等等,或者是一些其他的自定義事件。
在開發(fā)過程中,你可能會(huì)頻繁的用到事件綁定,v-on寫起來有點(diǎn)麻煩,所以上例中提供了兩種寫法,#2就是對#1寫法的縮寫。利用@代替v-on,這里不多說。
利用v-if或者v-show進(jìn)行條件判定
如果我們希望用戶在登錄之后才能看到歡迎彈窗,而如果沒有登錄則給它一個(gè)登錄界面。Vue會(huì)提供給我們v-if指令和v-show指令用來控制不同登錄狀態(tài)下的顯示內(nèi)容。
利用先前的例子,我們可以用loginStatus的值來控制是否登錄,如果是true則顯示輸入框和按鈕讓他能夠看到歡迎彈窗,但如果是false(即未登錄),則只能看到輸入賬號(hào)、密碼的輸入框和提交按鈕(暫時(shí)不進(jìn)行身份驗(yàn)證,只改變登錄狀態(tài))。
<div id="vueInstance">
//loginStatus為true時(shí)會(huì)顯示的section
<section v-if="loginStatus">
輸入您的姓名: <input type="text" v-model="name">
<button v-on:click="say">歡迎點(diǎn)擊</button>
<button @click="switchLoginStatus">退出登錄</button>
</section>
//loginStatus為false時(shí)會(huì)顯示的section
<section v-if="!loginStatus">
登錄用戶: <input type="text">
登錄密碼: <input type="password">
<button @click="switchLoginStatus">登錄</button>
</section>
</div>
<script>
var V = new Vue({
el : '#vueInstance',
data : {
name : '_Appian',
loginStatus : false
},
methods : {
say : function(){
alert('歡迎' + this.name);
},
switchLoginStatus : function(){
this.loginStatus = !this.loginStatus;
}
}
});
</script>
this的執(zhí)行就是實(shí)例V。this的指向是一個(gè)需要自己去搞懂的問題,這里不多說。
在上述例子中,只要把V-if換成v-show,一樣可以獲得等同的效果。同時(shí)v-if和v-show他們都支持v-else,但是綁定v-else命令的標(biāo)簽的前一兄弟元素必須有 v-if 或 v-show。
在上面的例子中,只要點(diǎn)擊“登錄”或者“退出登錄”按鈕都會(huì)觸發(fā)switchLoginStatus方法,只要觸發(fā)了這個(gè)方法就會(huì)導(dǎo)致loginStatus的狀態(tài)變化(在true和false中進(jìn)行切換),從而改變了html中的v-if的判斷條件結(jié)果的變化,基于當(dāng)前的loginStatus的布爾值的狀態(tài),使得顯示的section是不同狀態(tài)下的section。
v-show和v-if之間有什么區(qū)別呢?
在切換 v-if 塊時(shí),Vue有一個(gè)局部編譯/卸載過程,因?yàn)?v-if 之中的模板也可能包括數(shù)據(jù)綁定或子組件。v-if 是真實(shí)的條件渲染,因?yàn)樗鼤?huì)確保條件塊在切換當(dāng)中合適地銷毀與重建條件塊內(nèi)的事件監(jiān)聽器和子組件。
v-if 也是惰性的:如果在初始渲染時(shí)條件為假,則什么也不做——在條件第一次變?yōu)檎鏁r(shí)才開始局部編譯(編譯會(huì)被緩存起來)。
相比之下,v-show 簡單得多——元素始終被編譯并保留,只是簡單地基于 CSS 切換。
一般來說,v-if 有更高的切換消耗而 v-show 有更高的初始渲染消耗。因此,如果需要頻繁切換 v-show 較好,如果在運(yùn)行時(shí)條件不大可能改變 v-if 較好。
這個(gè)差別也許對你目前的開發(fā)來說并不重要,但是你還是要注意和留心,因?yàn)楫?dāng)你的項(xiàng)目開發(fā)變大的時(shí)候,這點(diǎn)會(huì)變得重要起來。
利用v-for輸出列表
如果你是經(jīng)營一個(gè)電商平臺(tái)的商人的話,你一定有很多頁面都需要渲染商品列表的輸出。v-for指令允許循環(huán)我們的數(shù)組對象,用 “element in arrayObj” 的方式,念作“循環(huán)arrayObj這個(gè)數(shù)據(jù)對象里的每一個(gè)element”。
下面的例子中,我們將會(huì)利用v-for指令循環(huán)輸出一個(gè)商品列表。每一個(gè)商品都會(huì)在一個(gè)li中,li中輸出商品的名稱、價(jià)格和商品類型。
<div id="vueInstance">
<ul>
<li v-for="el in products">
{{ el.name }} - ¥ {{ el. price }} - {{ el. category }}
</li>
</ul>
</div>
<script>
var V = new Vue({
el : '#vueInstance',
data : {
products : [
{name: 'microphone', price: 25, category: 'electronics'},
{name: 'laptop case', price: 15, category: 'accessories'},
{name: 'screen cleaner', price: 17, category: 'accessories'},
{name: 'laptop charger', price: 70, category: 'electronics'},
{name: 'mouse', price: 40, category: 'electronics'},
{name: 'earphones', price: 20, category: 'electronics'},
{name: 'monitor', price: 120, category: 'electronics'}
]
}
});
</script>
當(dāng)然了,data中的數(shù)組對象,可以不用像上面這樣定義也可以,我們可以從數(shù)據(jù)庫導(dǎo)入,或者是利用ajax請求得到。這里只是為了演示v-for。
有時(shí)候我們可能會(huì)需要拿到商品在數(shù)組對象里的對應(yīng)下標(biāo)。我們可以用$index來獲得。
//#1
<li v-for="el in products">
{{ $index }} - {{ el.name }} - ¥ {{ el. price }} - {{ el. category }}
</li>
//#2
<li v-for="(index,el) in products">
{{ index }} - {{ el.name }} - ¥ {{ el. price }} - {{ el. category }}
</li>
計(jì)算屬性Computed
計(jì)算屬性的應(yīng)用場景,一般是在有一個(gè)變量的值需要其他變量計(jì)算得到的時(shí)候,會(huì)用到。
比如,例如用戶在輸入框輸入一個(gè)數(shù) x,則自動(dòng)返回給用戶這個(gè)數(shù)的平方 x²。你需要對輸入框進(jìn)行數(shù)據(jù)綁定,然后當(dāng)數(shù)據(jù)修改的時(shí)候,就馬上計(jì)算它的平方。
<div id="vueInstance">
輸入一個(gè)數(shù)字: <input type="text" v-model="value">
<p>計(jì)算結(jié)果:{{ square }}</p>
</div>
<script>
var V = new Vue({
el : '#vueInstance',
data : {
value : 1
},
computed : {
square : function(){
return this.value * this.value;
}
}
});
</script>
計(jì)算屬性定義數(shù)值是通過定義一系列的function,就像我們先前定義methods對象的時(shí)候是一樣的。比如square方法是用來計(jì)算變量“square”的,其方法的返回值是兩個(gè)this.value的乘積。
接下來可以用computed做一個(gè)復(fù)雜一點(diǎn)例子。系統(tǒng)會(huì)隨機(jī)取一個(gè)1~10以內(nèi)的數(shù)字,用戶可以在輸入框隨機(jī)輸入一個(gè)1~10之內(nèi)的數(shù)字,如果剛好用戶的輸入和系統(tǒng)的隨機(jī)數(shù)剛好匹配,則游戲成功,反之失敗。
<div id="vueInstance">
輸入1~10內(nèi)的數(shù)字: <input type="text" v-model="value">
<p>計(jì)算結(jié)果:{{ resultMsg }}</p>
</div>
<script>
var V = new Vue({
el : '#vueInstance',
data : {
value : null,
randNum : 5//第一次隨機(jī)數(shù)為5
},
methods : {
getRandNum: function(min, max){
return Math.floor(Math.random() * (max - min + 1)) + min;
}
},
computed : {
resultMsg : function(){
if (this.value == this.randNum) {
this.randNum = this.getRandNum(1, 10);
return '你猜對了!';
} else {
this.randNum = this.getRandNum(1, 10);
return '猜錯(cuò)了,再來!';
}
}
}
});
</script>
后記
到此為止,你就已經(jīng)能夠掌握了Vue的基本使用,世界上最簡潔最漂亮的框架之一,它的構(gòu)建有著自己完整的設(shè)計(jì)思想,而且越來越流行。這個(gè)框架足夠小而輕,在你的開發(fā)中會(huì)給你帶來更加流暢的用戶體驗(yàn),并有效提高開發(fā)效率。上文中舉了一系列例子,都掌握了嗎?
相關(guān)文章
Vue頁面刷新記住頁面狀態(tài)的實(shí)現(xiàn)
這篇文章主要介紹了Vue頁面刷新記住頁面狀態(tài)的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-12-12
vue3使用elementPlus進(jìn)行table合并處理的示例詳解
虛擬數(shù)據(jù)中公司下有多個(gè)客戶,公司一樣的客戶,公司列需要合并,客戶如果一樣也需要合并進(jìn)行展示,所以本文給大家介紹了vue3使用elementPlus進(jìn)行table合并處理的實(shí)例,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
elementui之el-table-column日期格式顯示方式
文章介紹了如何使用formatter屬性對表格某一列的內(nèi)容進(jìn)行日期格式化,通過綁定日期格式化的方法實(shí)現(xiàn),展示了前端代碼的模板和方法,并給出了前端效果的展示2024-12-12
vue-cli下的vuex的簡單Demo圖解(實(shí)現(xiàn)加1減1操作)
這篇文章主要介紹了vue-cli下的vuex的簡單Demo(實(shí)現(xiàn)加1減1操作),本文圖文并茂給大家介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-02-02
用element的upload組件實(shí)現(xiàn)多圖片上傳和壓縮的示例代碼
這篇文章主要介紹了用element的upload組件實(shí)現(xiàn)多圖片上傳和壓縮的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02
vue項(xiàng)目中使用bpmn為節(jié)點(diǎn)添加顏色的方法
這篇文章主要介紹了vue項(xiàng)目中使用bpmn為節(jié)點(diǎn)添加顏色的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04
elementUI中input回車觸發(fā)頁面刷新問題與解決方法
這篇文章主要給大家介紹了關(guān)于elementUI中input回車觸發(fā)頁面刷新問題與解決方法,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用elementUI具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-07-07

