在上一節(jié)中我們了解了 DRF 逾雄,現(xiàn)在我們要開始學(xué)習(xí) Vue 了阀溶,這一前端神器。同樣的鸦泳,這不是官方文檔復(fù)讀機(jī)银锻,我們會(huì)講一些官方文檔沒有講的東西,如果你對本節(jié)中所涉及到的東西想有更深的了解做鹰, vue 官方文檔是個(gè)好去處击纬。一個(gè)好消息是,Vue 與 Django 的原理有著相通之處钾麸,大家應(yīng)該可以很輕松的掌握掉弛,只是有一些小的知識點(diǎn)細(xì)節(jié)需要明確。同時(shí) js 和 py 都支持面向?qū)ο缶幊涛棺撸源蠹以诳唇坛虝r(shí)殃饿,著重聯(lián)系面向?qū)ο蟮木幊趟季S,如果 js 代碼不理解芋肠,那就想想同樣的 python 代碼是怎么寫的乎芳。
本章會(huì)涵蓋以下知識點(diǎn):
- Vue 原理。
- 認(rèn)識組件帖池。
- Vue 特色語法奈惑。
Vue 的中文文檔已經(jīng)非常優(yōu)秀,作為國人開發(fā)的框架睡汹,對國人是非常友好的肴甸,并且官方文檔的入門教程是真的不錯(cuò),強(qiáng)烈建議大家去看看囚巴。
Vue 原理
對于 Vue 原在,很多人應(yīng)該聽說過 MVVM 模型友扰,但是同 MTV 一樣,很少有人能清楚的解釋這到底是怎么回事庶柿。
圖片來源:https://academy.realm.io/cn/posts/mobilization-lukasz-mroz-mvvm-coordinators-rxswift/
View: 展示數(shù)據(jù)的部分村怪,也就是我們可以在頁面上看到的 UI 。 View 使用 ViewModel 來做出對應(yīng)的狀態(tài)改變浮庐。同時(shí)甚负,View 不會(huì)也不能進(jìn)行改變數(shù)據(jù)的操作,它是通過 ViewModel 來修改數(shù)據(jù)的审残。也就是說梭域,這里的 View 就真的只是個(gè) View ,就像是被渲染之后的模板一樣搅轿,就是一個(gè) html 文件碰辅,什么數(shù)據(jù)操作都不能做。
ViewModel: 數(shù)據(jù)的業(yè)務(wù)邏輯部分介时。所有的業(yè)務(wù)邏輯都在這里。不僅包含數(shù)據(jù)的處理邏輯凌彬,還包括 View 的邏輯都在這里了沸柔,所以叫做 ViewModel 。比如我們之前寫的 code-options
的部分铲敛,不同的數(shù)據(jù)對應(yīng)不同的 View 狀態(tài)褐澎。這和 Djanogo 的模板很相似,我們在模板中編寫了 html 相應(yīng)的邏輯伐蒋,最后由模板引擎渲染成固定的 html 文檔工三。大家可以把這部分理解為前端的模板引擎,不僅包含視圖邏輯先鱼,還包含對后端的數(shù)據(jù)處理俭正。
Model: 儲存數(shù)據(jù)的地方。也就是我們的 Store 了焙畔,它負(fù)責(zé)向后端 API 發(fā)起請求掸读,儲存收到的數(shù)據(jù)。
我們來看看這樣一個(gè) MVVM 流程是怎樣走完的:
- 用戶看到了一個(gè)按鈕(View)宏多,點(diǎn)擊了它(View 發(fā)出信號儿惫,ViewModel 捕捉信號)。
- ViewModel 收到信號伸但,根據(jù) View 邏輯肾请,此時(shí)應(yīng)該從 Store 中獲取數(shù)據(jù),數(shù)據(jù)在處理之后更胖,數(shù)據(jù)傳到 View 中铛铁。
- Store 收到請求隔显,發(fā)現(xiàn)現(xiàn)在不需要重新請求數(shù)據(jù),就直接把數(shù)據(jù)給了發(fā)起請求的 ViewModel 避归。
所以荣月,總結(jié)一下,MVVM 的唯一不同之處就是把視圖邏輯和數(shù)據(jù)邏輯放在了一起梳毙,稱為“ViewModel”哺窄,View 的邏輯也被看成了是數(shù)據(jù)的一部分。剩下的部分和 Django 其實(shí)差不多账锹。
認(rèn)識組件
在開始之前萌业,我們需要做一些準(zhǔn)備工作。建立如下文件結(jié)構(gòu):
vue_learn/
vue.js
index.js
bootstrap.js
jquery.js
bootstrap.css
index.html
vue.js: vue 的源文件奸柬,可以直接從這里復(fù)制粘貼生年,也可以直接從我的 github 倉庫中拉取。
index.js: 空文件廓奕,我們將會(huì)在這里學(xué)習(xí) vue 抱婉。
bootstrap.js: bootstrap 的 js 文件∽婪郏可以從上一章的項(xiàng)目中復(fù)制蒸绩。
bootstrap.css: bootstrap 的 css 文件×蹇希可以從上一章的項(xiàng)目中復(fù)制患亿。
jquery.js: bootstrap.js 的依賴,必須使用押逼〔脚海可以從上一章的項(xiàng)目中復(fù)制。
在 index.html 中寫入下列代碼:
<!DOCTYPE html>
<html>
<head>
<title>Vue-learn</title>
<link rel="stylesheet" type="text/css" href="bootstrap.css">
</head>
<body>
<div id="app"></div>
<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
<script src="vue.js"></script>
<script src="index.js"></script>
</body>
</html>
準(zhǔn)備工作做完了挑格。編輯器中打開你的 index.js 和 index.html咙冗,同時(shí)用瀏覽器打開 index.html ,以便我們隨時(shí)查看編寫的效果漂彤。這里需要你調(diào)整好自己的窗口規(guī)劃乞娄,最好能夠使用多任務(wù)桌面,如果你使用的 win7 显歧,Dexport
是個(gè)支持這項(xiàng)功能的好軟件仪或,支持快捷鍵切換桌面,特別方便士骤,并且還是免費(fèi)的范删。
組件
組件是什么?
正如我們在第一章中編寫 html 一樣拷肌,先把頁面的框架搭好到旦,再往每個(gè)部分里填 UI 旨巷,這些 UI 便被稱為組件了。我們的 code-list 是一個(gè)組件添忘,code-options 按鈕組也是組件采呐,我們在需要的時(shí)候渲染它們。就像是搭積木一樣搁骑,組件是積木斧吐,網(wǎng)頁就是我們用不同的積木搭建起來的堡壘。
把眼光放的再開一點(diǎn)看仲器,我們的框架結(jié)構(gòu)本身煤率,也是個(gè)組件。只是這些組件沒有形狀乏冀,只有結(jié)構(gòu)蝶糯,等待其它組件被填充進(jìn)去。在頁面中辆沦,一切皆可為組件昼捍,相信大家在了解 REST 一切及資源之后理解這個(gè)應(yīng)該不難。
所以肢扯,在我們之前寫的前端代碼中妒茬,那些包含模板字符串的函數(shù)就是我們組件了,我們可以隨時(shí)調(diào)用他們來搭建頁面鹃彻。
組件是實(shí)例。
因?yàn)槲覀兪褂玫氖?Vue 妻献,所以應(yīng)該使用 Vue 來構(gòu)建我們組件蛛株。我們在 python 知道類和實(shí)例的概念,在這里我們說的實(shí)例也就是 Vue 類的實(shí)例育拨。所以谨履,象這樣寫我們就有了一個(gè) Vue 實(shí)例:
let vueInstance = new Vue({...}) //{...} 為選項(xiàng)對象
既然是實(shí)例,那么 Vue 類有的屬性和方法熬丧,Vue 實(shí)例也就是組件也應(yīng)該有這些方法笋粟。同時(shí),他們的參數(shù)析蝴,也就是選項(xiàng)對象也應(yīng)該相同害捕。然而事實(shí)是,有少數(shù)幾個(gè)選項(xiàng)只在運(yùn)行 new
時(shí)有效闷畸。至于為什么這樣做尝盼,在下面會(huì)提到,
剛才我們也提到佑菩,組件之間可以相互組合盾沫,共同構(gòu)成一個(gè)“大組件”裁赠,也就是我們的網(wǎng)頁。那怎么把 Vue 和頁面中的 html 相聯(lián)系起來呢赴精?
如果我們想要使用一個(gè)組件佩捞,我們需要告訴 Vue 我們需要把這個(gè)組件放在哪里。有幾種方式可以選擇蕾哟,我們一個(gè)一個(gè)來看看一忱。
第一種,只使用 el
選項(xiàng)渐苏。僅僅在 new
時(shí)有效掀潮。
index.html
<div id="app">
{{ message }}
</div>
index.js
let cp = new Vue({
el: '#app',
data:function(){
return {
message:'Hello Vue!'
}
}
})
保存他們并刷新你的瀏覽器,你會(huì)看到在 html 中本來的 {{ message }}
部分被替換為了 Hello Vue!
琼富。
我們使用 el
選項(xiàng)仪吧,告訴 Vue 我們要把匹配 #app
的 html 元素作為組件。把一個(gè)元素作為組件鞠眉,也就是相當(dāng)于告訴 Vue 我們的組件要放在這里了薯鼠。
看到 {{ }}
我相信大家一定都非常熟悉了,這不就是模板的語法嗎械蹋?那選項(xiàng)中的 data
參數(shù)是做什么用的呢出皇?正如它的名字一樣,這是給組件提供數(shù)據(jù)的地方哗戈。為什么使用的是函數(shù)來返回?cái)?shù)據(jù)而不是直接把 data
定義為一個(gè)對象呢郊艘?保持你的好奇心。這個(gè)問題我們之后再來解答唯咬,現(xiàn)在你可以簡單的就像理解我們在前端管理 API 時(shí)所做的那樣纱注,為了方便變動(dòng)數(shù)據(jù)。
第二種方式胆胰,使用 template
和 el
選項(xiàng)狞贱。
index.html
<div id="app">
{{ message }}
</div>
<div id="app2"></div>
index.js
let cp2 = new Vue({
el:'#app2',
template:`
<h1>{{ message }}</h1>`,
data:function(){
return {
message: 'Hello Component 2!'
}
}
})
保存他們并刷新你的瀏覽器,你會(huì)看到在 html 中蜀涨,本來的 <div id="app2"></div>
,被替換為了 <h1>Hello Component 2!</h1>
瞎嬉。
我們可以把本來的組件寫在 template
選項(xiàng)中,使用 el
選項(xiàng)告訴 Vue 我們會(huì)在哪里放這個(gè)組件厚柳,Vue 會(huì)用 template
的內(nèi)容替換被匹配到的元素氧枣。替換,也是一種告訴 Vue 我們要把組件放到哪兒的方法别垮。需要注意的是挑胸,template
只能有一個(gè)外層標(biāo)簽,因?yàn)橛卸鄠€(gè)的話 Vue 就不知道該把哪個(gè)元素替換到目標(biāo)標(biāo)簽上去宰闰。
第三種茬贵,使用 $mount
和 template
簿透。
index.html
<div id="app2"></div>
<div id="app3"></div>
index.js
let cp3 = new Vue({
template: `<h1>{{ message }}</h1>`,
data: function(){
return {
message:'Hello Component 3!'
}
}
})
cp3.$mount('#app3')
保存他們并刷新你的瀏覽器,你會(huì)看到在 html 中解藻,本來的 <div id="app3"></div>
,被替換為了 <h1>Hello Component 3!</h1>
老充。
當(dāng)沒有使用 el
指定要把一個(gè)組件放在哪里時(shí),這個(gè)組件處于“未掛載”狀態(tài)螟左。我們可以在創(chuàng)建一個(gè)組件之后啡浊,使用其 .$mount
方法,將它“掛載”到一個(gè)元素上胶背,這個(gè)元素會(huì)被 template
替換 掉巷嚣。
組合組件
正如我們剛才所說,組件是可以被“組合”的钳吟。按照剛才的寫法廷粒,我們應(yīng)該怎樣將組件們結(jié)合起來呢?也就是說红且,我們怎樣做才能讓組件知道有其它的組件存在呢坝茎?
index.html
<div id="app5"></div>
index.js
let cp4 = {
template:'<h1>{{ message }}</h1>',
data:function(){
return {
message: 'Hello Component 4!'
}
}
}
let cp5 = new Vue({
el:'#app5',
template:`
<div class="text-center">
<cp-4></cp-4>
{{ msg }}
</div>`,
components:{
'cp-4':cp4
},
data:function(){
return {
msg:"I'm Component 5!"
}
}
})
保存他們并刷新你的瀏覽器,你會(huì)看到我們的組件成功的被組合在了一起暇番,可以查看一下瀏覽器嗤放,看看他們是否都在同一個(gè)div
下。
組合組件的方法就是使用 components
選項(xiàng)壁酬,我們不需要傳給 components
Vue 實(shí)例次酌,只需要傳子組件的名字作為屬性,它的選項(xiàng)作為值就好了舆乔。以上的過程岳服,我們稱為“注冊組件”這樣,組件就可以使用在 components
中的其它組件了蜕煌。并且派阱,只需要像使用普通的 html 一樣就可以使用它了诬留。
剛才說的是“局部注冊”斜纪,也就是只是把組件和某個(gè)特定的組件組合起來。但是有時(shí)候文兑,我們希望能夠“全局注冊”這個(gè)組件盒刚,也就是說,我們希望能夠在所有的組件中使用它绿贞。 Vue 為我們提供了全局注冊的方法因块。
index.html
<div id="app5"></div>
<div id="app6"></div>
<div id="app7"></div>
index.js
Vue.component('global-cp',{
template:`<h1>{{ msg }}</h1>`,
data:function(){
return {
msg:"I'm global!"
}
}
})
let cp6 = new Vue({
el:'#app6',
template:`<div>
I'm app6!
<global-cp></global-cp>
</div>`
})
let cp7 = new Vue({
el:'#app7',
template:`<div>
<global-cp></global-cp>
{{ msg }}
</div>`,
data:function(){
return {
msg:"I'm app7!"
}
}
})
保存他們并刷新你的瀏覽器,你會(huì)看到我們的全局組件已經(jīng)起作用了籍铁。我們使用的是 Vue 類的方法來添加全局組件涡上。類的就是實(shí)例的趾断,所以類有了某個(gè)組件,那么用這個(gè)類生成的實(shí)例也應(yīng)該有這些組件吩愧。
正確的使用組件
剛才我們說道芋酌,一個(gè)網(wǎng)頁也可以是一個(gè)組件。也就是說雁佳,我們可以先創(chuàng)建一個(gè)空的組件脐帝,然后讓這個(gè)組件來容納其它的組件,這樣我們就可以實(shí)現(xiàn)僅僅使用 Vue 就可以對網(wǎng)頁進(jìn)行全權(quán)的控制糖权,從而實(shí)現(xiàn)許多酷炫的功能堵腹。SPA(Single Page Application,單頁應(yīng)用)就是一個(gè)很好的范例星澳。整個(gè)應(yīng)用只有一個(gè)網(wǎng)址疚顷,網(wǎng)頁的所有變動(dòng)都是組件的變動(dòng),同時(shí)募判,這也減輕了前端的壓力荡含,不用再去寫那么多頁面,只需要寫變化的組件就行了届垫。
所以释液,組件的一般寫法是:
1. 先寫一個(gè)空的組件作為組件入口。
2. 通過在這個(gè)空的組件中組合其它組件來達(dá)到組合成網(wǎng)頁的目的
刪除 index.html
中所有的 div
元素装处,刪除 index.js
中的所有代碼误债,編寫代碼如下:
index.html
<div id="app"></div>
index.js
let navBar = {
template:`
<nav class="navbar navbar-default">
<div class="container-fluid">
<ul class="nav navbar-nav">
<li class="active"><a href="{{ home }}">Home</a></li>
<li><a href="{{ about }}">About</a></li>
</ul>
</div>
</nav>
`,
data:function(){
return {
home:'http://example.com/',
about:'http://example.com/about'
}
}
}
let mainContent = {
template:`
<h1>{{ content }}</h1>
`,
data:function(){
return {
content:'This is main content!'
}
}
}
let app = {
template:`
<div class="container">
<div class="row">
<nav-bar></nav-bar>
</div>
<div class="row">
<main-content></main-content>
</div>
</div>`,
components:{
'nav-bar':navBar,
'main-content':mainContent
}
}
let root = new Vue({
el:'#app',
template:`<app></app>`,
components:{
'app':app
}
})
保存他們并刷新你的瀏覽器,你看到的會(huì)是這樣:
我們僅僅調(diào)用了一次 new Vue()
妄迁,把 root
作為根組件寝蹈。組件 root
基本上是組件 app
構(gòu)成的,為什么不直接把 app
的邏輯放入 root
中呢登淘?因?yàn)槲覀兊?app
可能不止一個(gè)箫老,可能隨時(shí)會(huì)被替換成其它的 app
組件,比如我們的網(wǎng)頁有兩套布局模式黔州,一套為移動(dòng)端布局耍鬓,一套為PC端布局,我們可能會(huì)根據(jù)需求來更換布局流妻,要是直接寫死在根組件里牲蜀,會(huì)十分的不便。
關(guān)于組件绅这,我們就暫時(shí)學(xué)到這里涣达。在最后一節(jié),我們將會(huì)學(xué)習(xí)更多關(guān)于組件的知識。
Vue 組件特色語法度苔。
有許多的特殊語法可以在組件中使用匆篓,幫助我們提高開發(fā)的效率。如同模板一樣寇窑,它們都有自己的語法奕删。
準(zhǔn)備工作
在 vue_learn
下新建一個(gè) html 文檔,名為 grammer.html
疗认,編寫如下代碼:
grammer.html
<!DOCTYPE html>
<html>
<head>
<title>Grammer</title>
</head>
<body>
<div id="app"></div>
<script src="vue.js"></script>
<script type="text/javascript">
</script>
</body>
</html>
我們接下來的大部分工作都將會(huì)在空的 script
標(biāo)簽中完成完残。
{{ }}
data
在 Django 模板中,{{ }}
中是用來寫變量的横漏,在渲染時(shí)谨设,變量會(huì)被替換為相應(yīng)的變量值。 在 Vue 中缎浇,{{ }}
也做了同樣的事情扎拣,但不一樣的是,這個(gè)變量值是動(dòng)態(tài)的素跺,也就是“響應(yīng)式”的二蓝。
grammer.html
<script type="text/javascript">
let app = new Vue({
el:'#app',
template:'<h1>{{ msg }}</h1>',
data: function(){
return {
msg:'Grammer'
}
}
})
setInterval(function(){
if (app.msg=='Grammer'){
app.msg = 'Vue'
} else {
app.msg = 'Grammer'
}
}, 500)
</script>
保存并在瀏覽器中打開,你會(huì)看到 'Vue' 與 'Grammer' 之間在不停的切換指厌。
仔細(xì)觀察我們代碼刊愚,我們發(fā)現(xiàn):
- 我們并沒有直接使用
app.data.msg
來改變數(shù)據(jù),而是使用app.msg
來改變msg
屬性的值踩验。 - 雖然我們是在實(shí)例化組件之后才改變的
msg
屬性值鸥诽,但是數(shù)據(jù)變化在 UI 上依然被表現(xiàn)出來了。
對于第一條箕憾,反應(yīng)快的同學(xué)已經(jīng)發(fā)現(xiàn)了牡借,我們傳給 Vue 的是它的選項(xiàng)對象,選項(xiàng)對象又不一定是作為 Vue 實(shí)例屬性來使用的袭异。事實(shí)上钠龙,如果想要訪問實(shí)例的原始 data
對象,應(yīng)該使用實(shí)例的 $data
屬性御铃。但是碴里,我們 data
選項(xiàng)返回的數(shù)據(jù)對象卻成了 Vue 實(shí)例的屬性。所謂數(shù)據(jù)對象畅买,就是一個(gè)純粹的 key/value 對并闲,和我們的 python 字典一樣细睡。Vue 官方也建議谷羞,數(shù)據(jù)對象最好只有純粹的鍵值對,因?yàn)閿?shù)據(jù)對象的原型鏈將會(huì)不會(huì)起作用。
為什么 data
返回的數(shù)據(jù)對象會(huì)成為 Vue 實(shí)例的屬性呢湃缎?因?yàn)?Vue 在生成組件實(shí)例時(shí)犀填,會(huì)把 data
返回的數(shù)據(jù)對象遞歸的設(shè)置為組件實(shí)例的 getter/setter
。 或許這里的 getter/setter
不怎么好理解嗓违,它的原理其實(shí)和 python 的描述符類似九巡。getter
如同 __get__
方法,攔截了讀取數(shù)據(jù)的操作蹂季,setter
如同 __set__
冕广,攔截了賦值操作。當(dāng)有任何的數(shù)據(jù)變動(dòng)時(shí)偿洁,Vue 實(shí)例的 setter
在完成賦值操作之后撒汉,還會(huì)告訴另外一個(gè)負(fù)責(zé)繪制 UI 的方法“該修改 UI 上的數(shù)據(jù)啦”,這樣就實(shí)現(xiàn)了動(dòng)態(tài)的“響應(yīng)式”操作涕滋,當(dāng)然睬辐,真正的響應(yīng)式原理還需要考慮到更多的東西裆甩。
既然我們知道了數(shù)據(jù)對象會(huì)被設(shè)置為實(shí)例的屬性饱普,所以我們完全可以在編寫組件時(shí)直接使用 this
來訪問組件屬性。
回到 {{ }}
背镇,當(dāng) Vue 遇到 {{ }}
時(shí)锨用,它會(huì)在組件的數(shù)據(jù)對象中尋找對應(yīng)的屬性值丰刊。所以,如果想要在 {{ }}
中使用某個(gè)變量增拥,需要先在數(shù)據(jù)對象中定義它藻三,不然就會(huì)出錯(cuò)。
computed
computed
是選項(xiàng)對象的屬性之一跪者,我們可以使用這個(gè)選項(xiàng)對數(shù)據(jù)做一些復(fù)雜的處理棵帽。刪除 grammer.html
中我們編寫組件的 script
標(biāo)簽代碼。重新編寫如下:
grammer.html
<script type="text/javascript">
let app = new Vue({
el:'#app',
template:'<p>Hello, {{ name }}. {{ greeting }}</p>',
data: function(){
return {
name:'Ucag'
}
},
computed:{
greeting: function(){
return 'I am Vue' + 'Nice to meet you ' + this.name
}
}
})
</script>
保存并在瀏覽器中打開渣玲,你會(huì)看到瀏覽器輸出了 Hello, Ucag. I am Vue Nice to meet you Ucag
逗概。computed
中的數(shù)據(jù)成功的被 {{ }}
語法獲取。
computed
選項(xiàng)中的鍵被成為“計(jì)算屬性”忘衍,Vue 會(huì)把這些屬性綁定到組件中逾苫,也就是說,我們同樣也可以用 this
來訪問他們枚钓。 那它和 data
選項(xiàng)的差別在哪里呢铅搓?
-
computed
中的計(jì)算結(jié)果會(huì)被緩存。通過例子搀捷,我們可以看出星掰,computed
的每個(gè)屬性值需要是一個(gè)函數(shù)多望。這個(gè)函數(shù)的返回值會(huì)被緩存。這個(gè)特性是很有用的氢烘,比如我們可以把對 API 的請求寫在這里怀偷,當(dāng)在使用組件時(shí),可以放心的調(diào)用計(jì)算屬性播玖,而不用擔(dān)心多余和不必要的請求椎工。通過 2 的例子更能說明計(jì)算屬性的緩存特點(diǎn)。 - 更新觸發(fā)機(jī)制不同蜀踏。數(shù)據(jù)對象维蒙,也就是
data
的返回的對象被更新之后,UI 會(huì)同時(shí)更新果覆。但是對于計(jì)算屬性就不會(huì)觸發(fā)更新木西,也就是說屬性不會(huì)重新計(jì)算,得到的值還是原來的計(jì)算值随静。
要是此時(shí)你在瀏覽器的控制臺輸入:
>app.greeting = 'Good morning'
<: 'Good moring'
>app.gretting
<: "I am Vue Nice to meet you Ucag"
我們可以看到八千,gretting
的值還是原來緩存的值。那么如何才能觸發(fā)計(jì)算屬性的更新呢燎猛?只有在計(jì)算屬性依賴的數(shù)據(jù)對象的屬性改變的時(shí)候才會(huì)觸發(fā)更新恋捆。
>app.name = 'Ace'
<: 'Ace'
>app.greeting
<: "I am Vue Nice to meet you Ace"
我們可以看到計(jì)算屬性已經(jīng)重新計(jì)算了。
所以重绷,如何合理使用計(jì)算屬性呢沸停?當(dāng)你遇到下列情況的時(shí)候應(yīng)該使用計(jì)算屬性:
- 數(shù)據(jù)要經(jīng)過復(fù)雜的處理。我們可以把復(fù)雜的數(shù)據(jù)處理步驟放在這里昭卓,在一次處理之后結(jié)果就會(huì)被緩存愤钾。
- 不希望主動(dòng)的響應(yīng)式變化。我們可以看到候醒,計(jì)算屬性是“被動(dòng)響應(yīng)”的能颁,只有在依賴的數(shù)據(jù)對象屬性改變之后才會(huì)重新計(jì)算。
既然被稱為計(jì)算屬性倒淫,computed
提供的數(shù)據(jù)處理功能不局限于簡單的調(diào)用屬性對應(yīng)的函數(shù)伙菊。雖然那計(jì)算屬性的觸發(fā)是取決于數(shù)據(jù)對象,但是我們依然可以讓計(jì)算屬性在被直接改變時(shí)做一些事情敌土。我們還可以對屬性設(shè)置 getter
和 setter
镜硕。重新編寫 app
組件如下:
grammer.html
let app = new Vue({
el:'#app',
template:'<p>Hello, {{ name }}. {{ greeting }}</p>',
data: function(){
return {
name:'Ucag'
}
},
computed:{
greeting: {
get: function(){
return 'I am Vue. ' + 'Nice to meet you ' + this.name
},
set: function(value){
console.log('You can not change greeting to ' + value)
}
}
}
})
保存并在瀏覽器中打開,打開你的瀏覽器控制臺返干,輸入下面的代碼:
>app.greeting = 'Good morning'
<: You can not change greeting to Good morning
setter
運(yùn)行成攻了兴枯。
methods
我們可以把我們需要在組件中使用的函數(shù)定義在這里,我們可以在 {{ }}
中調(diào)用它矩欠。修改我們的組件如下:
let app = new Vue({
el:'#app',
template:`<div>
<p>{{ say('hello') }} to {{ name }}</p>
</div>`,
data: function(){
return {
name:'Ucag'
}
},
methods:{
say: function(value){
return value.toUpperCase()
}
}
})
保存并在瀏覽器中打開财剖,你會(huì)看到 {{ }}
成功調(diào)用了 say
函數(shù)悠夯。同樣的,methods
中的函數(shù)會(huì)被綁定到組件上峰伙,可以使用 this
來訪問它。
我們使用函數(shù)返回了一個(gè)經(jīng)過處理之后的數(shù)據(jù)该默,并且接收了參數(shù)瞳氓。那它和計(jì)算屬性有什么不同呢?當(dāng)methods
中的函數(shù)被調(diào)用時(shí)栓袖,每一次的結(jié)果都是函數(shù)再次運(yùn)行之后的匣摘,也就是說,它的結(jié)果不會(huì)被緩存裹刮。我們可以把組件相關(guān)的 UI 動(dòng)作定義在這里音榜,比如在點(diǎn)擊按鈕之后需要執(zhí)行的動(dòng)作。
JavaScript表達(dá)式
剛才我們可以看到捧弃,{{ }}
中除了可以寫我們需要訪問的屬性之外赠叼,還可以執(zhí)行函數(shù)。其實(shí)违霞,{{ }}
還可以寫 javascript 表達(dá)式嘴办。
像下面這樣也是正確的。
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
v-bind 與 v-on
有的時(shí)候买鸽,我們希望能夠?qū)?biāo)簽的屬性有更多的控制涧郊。比如,動(dòng)態(tài)的生成屬性眼五,觸發(fā)我們自定義的事件動(dòng)作妆艘。
重新編寫我們的組件:
grammer.html
let app = new Vue({
el:'#app',
template: `<div>
<input
type="text"
placeholder="username"
v-on:input="changeHref">
<a v-bind:href="UserLink">Go Home</a>
</div>`,
data:function(){
return {
UserLink:'#'
}
},
methods:{
changeHref: function(event){
let username = event.target.value
if (username){
this.UserLink = 'http://www.example.com/' + username
} else {
this.UserLink = '#'
}
}
}
})
保存并在瀏覽器中打開,嘗試輸入幾個(gè)數(shù)據(jù)看幼,你會(huì)看到這樣的效果批旺。
v-
開頭的東西稱為“指令”朱沃。
我們在標(biāo)簽的事件上使用了 v-on:event="handler"
語法,來告訴 Vue 茅诱,當(dāng) event
事件發(fā)生時(shí)逗物,調(diào)用 handler
函數(shù)。 Vue 會(huì)默認(rèn)的往這個(gè)函數(shù)里傳一個(gè) event
參數(shù)瑟俭,event
代事件對象翎卓。我們使用 v-bind:property="value"
來告訴 Vue ,property
屬性的值等于組件的 value
屬性值摆寄。也就是說失暴,如果你使用了 v-on
或者 v-bind
等坯门,那么等號后面的東西就不再會(huì)被解釋為字符串,而是一個(gè) js 表達(dá)式逗扒。
他們都有自己的縮寫形式古戴,v-bind:property="value
可以寫為 :property=value
,v-on:event="handler"
可以寫為 @event="handler"
矩肩。所以像這樣寫也是可以的:
let app = new Vue({
...
template: `<div>
<input
type="text"
placeholder="username"
@:input="changeHref">
<a :href="UserLink">Go Home</a>
</div>`,
...
})
v-if 與 v-for
我們可以在 Django 的模板中使用 {% for item in iterable %}
來迭代對象现恼,使用 {% if conditino %}
來做條件判斷。同樣的黍檩,Vue 也提供了這些功能叉袍。
把我們的組件重新編寫如下:
let app = new Vue({
el:'#app',
template: `<ul>
<li v-for="person in personList">
<p>Name: {{ person.name }}</p>
<p v-if="person.age > 18">Age: {{ person.age }}</p>
</li>
</ul>`,
data:function(){
return {
personList:[
{name:'Ucag',age:'18'},
{name:'Ace',age:'20'},
{name:'Lily',age:'22'}]
}
}
})
保存并在瀏覽器中打開,你會(huì)看到瀏覽器渲染出了我們的列表刽酱。
v-for
用于迭代某個(gè)標(biāo)簽喳逛,指令的基本語法是:
<tag v-for="alias in expression"></tag>
alias
是當(dāng)前迭代對象的別名。
當(dāng)被迭代對象是 Array
棵里,string
润文,number
時(shí),可以使用以下兩種語法迭代:
<tag v-for="alias in items"></tag>
<tag v-for="(item, index) in items"></tag>
在第二種迭代方式中殿怜,index
是其索引转唉,也就是從 0 開始。
當(dāng)?shù)鷮ο笫?Object
時(shí)稳捆,可以使用以下三種方式迭代:
<tag v-for="val in objec"></tag>
<tag v-for="(val, key) in object"></tag>
<tag v-for="(val, key, index) in object"></tag>
第一種是直接迭代對象的屬性值赠法。第二種則包含了屬性值和屬性。第三種相對第二種多了一個(gè)索引值乔夯。
v-if
用于判斷某個(gè)標(biāo)簽砖织,基本語法是:
<tag v-if="conditino"></tag>
如果條件成立則渲染這個(gè) tag
,不成立則不渲染末荐。同樣的侧纯,它還有自己其它的配套語法。
// 和 v-else 一起使用
<div v-if="conditino">
Now you see me
</div>
<div v-else>
Now you don't
</div>
//和 v-else-if 一起使用
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
不過需要注意的是甲脏,v-else
或者 v-else-if
必須緊跟在 v-if
后使用眶熬,不然這些指令不會(huì)被識別。
當(dāng)同時(shí)在一個(gè)標(biāo)簽中使用 v-if
與 v-for
時(shí)块请,總是會(huì)先執(zhí)行 v-for
娜氏,再執(zhí)行 v-if
。也就是說墩新,v-for
的優(yōu)先級要高贸弥。
本節(jié)的 Vue 基礎(chǔ)就講完了。我們只是簡單的入門了 Vue 海渊,但是僅僅這些知識就已經(jīng)夠我們編寫最基本的頁面了绵疲。在下一節(jié)哲鸳,我們將會(huì)運(yùn)用前兩節(jié)學(xué)到的知識,重構(gòu)我們的 APP 盔憨。不過由于最近期末考試了徙菠,下一次更應(yīng)該是在一月十號之后了。最后祝大家冬至快樂~