Django RESTful 系列教程(三)(中)

在上一節(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):

  1. Vue 原理。
  2. 認(rèn)識組件帖池。
  3. Vue 特色語法奈惑。

Vue 的中文文檔已經(jīng)非常優(yōu)秀,作為國人開發(fā)的框架睡汹,對國人是非常友好的肴甸,并且官方文檔的入門教程是真的不錯(cuò),強(qiáng)烈建議大家去看看囚巴。

Vue 原理

對于 Vue 原在,很多人應(yīng)該聽說過 MVVM 模型友扰,但是同 MTV 一樣,很少有人能清楚的解釋這到底是怎么回事庶柿。

MVVM 模型

圖片來源: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 流程是怎樣走完的:

  1. 用戶看到了一個(gè)按鈕(View)宏多,點(diǎn)擊了它(View 發(fā)出信號儿惫,ViewModel 捕捉信號)。
  2. ViewModel 收到信號伸但,根據(jù) View 邏輯肾请,此時(shí)應(yīng)該從 Store 中獲取數(shù)據(jù),數(shù)據(jù)在處理之后更胖,數(shù)據(jù)傳到 View 中铛铁。
  3. 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):

  1. 我們并沒有直接使用 app.data.msg 來改變數(shù)據(jù),而是使用 app.msg 來改變 msg 屬性的值踩验。
  2. 雖然我們是在實(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)的差別在哪里呢铅搓?

  1. 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)。
  2. 更新觸發(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ì)算屬性:

  1. 數(shù)據(jù)要經(jīng)過復(fù)雜的處理。我們可以把復(fù)雜的數(shù)據(jù)處理步驟放在這里昭卓,在一次處理之后結(jié)果就會(huì)被緩存愤钾。
  2. 不希望主動(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è)置 gettersetter镜硕。重新編寫 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=valuev-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-ifv-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)該是在一月十號之后了。最后祝大家冬至快樂~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末郁岩,一起剝皮案震驚了整個(gè)濱河市婿奔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驯用,老刑警劉巖脸秽,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儒老,死亡現(xiàn)場離奇詭異蝴乔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)驮樊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門薇正,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人囚衔,你說我怎么就攤上這事挖腰。” “怎么了练湿?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵猴仑,是天一觀的道長。 經(jīng)常有香客問我肥哎,道長辽俗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任篡诽,我火速辦了婚禮崖飘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杈女。我一直安慰自己朱浴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布达椰。 她就那樣靜靜地躺著翰蠢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啰劲。 梳的紋絲不亂的頭發(fā)上躏筏,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機(jī)與錄音呈枉,去河邊找鬼趁尼。 笑死埃碱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酥泞。 我是一名探鬼主播砚殿,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼芝囤!你這毒婦竟也來了似炎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤悯姊,失蹤者是張志新(化名)和其女友劉穎羡藐,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悯许,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仆嗦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了先壕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘩扼。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垃僚,靈堂內(nèi)的尸體忽然破棺而出集绰,到底是詐尸還是另有隱情,我是刑警寧澤谆棺,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布栽燕,位于F島的核電站,受9級特大地震影響改淑,放射性物質(zhì)發(fā)生泄漏碍岔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一溅固、第九天 我趴在偏房一處隱蔽的房頂上張望付秕。 院中可真熱鬧,春花似錦侍郭、人聲如沸询吴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猛计。三九已至,卻和暖如春爆捞,著一層夾襖步出監(jiān)牢的瞬間奉瘤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盗温,地道東北人藕赞。 一個(gè)月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像卖局,于是被迫代替她去往敵國和親斧蜕。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

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

  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨(dú)立版本砚偶,Vue即被注冊為全局變量批销,可以在頁面使用了。 如果希望搭建...
    Awey閱讀 11,027評論 4 129
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容染坯,還有我對于 Vue 1.0 印象不深的內(nèi)容均芽。關(guān)于...
    云之外閱讀 5,050評論 0 29
  • Vue 實(shí)例 屬性和方法 每個(gè) Vue 實(shí)例都會(huì)代理其 data 對象里所有的屬性:var data = { a:...
    云之外閱讀 2,214評論 0 6
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)单鹿,斷路器掀宋,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 姓名:楊忠誠 公司:慧友冠源科技&272期六項(xiàng)精進(jìn)努力二組&廣東盛和塾稻牙二組 【日精進(jìn)打卡第121天】' 【知~...
    楊忠誠閱讀 215評論 0 0