此篇是關(guān)于 Vue 的總結(jié)审姓。Js 的總結(jié)請見前一篇:Vue + ElementUI 后臺管理系統(tǒng)項(xiàng)目心得(一)
話說過完年回來赴肚,仿佛一夜之間身邊的人都在談?wù)?Vue,相關(guān)的組件也如雨后春筍一般涌現(xiàn)出來,比如大名鼎鼎的 Element UI
吼畏、iView
還有不久前剛發(fā)布的 ATUI
昔汉,這些組件庫雖然實(shí)現(xiàn)方式和接口格式有所不同懈万,但大都界面美觀,體驗(yàn)流暢挤庇,可以說和 Vue 框架提供的良好性能是密不可分的钞速。
Vue 是一個上手簡單,卻富有內(nèi)涵的框架嫡秕,既可以像使用 jQuery
一樣簡單地通過 <script>
標(biāo)簽引入渴语,也支持通過打包工具構(gòu)建。
// 一個簡單的title.vue模板文件昆咽,同時具備了Web三要素:結(jié)構(gòu)層驾凶、表現(xiàn)層和行為層牙甫。
<template>
<div class="box">
<span class="title-text">title</span>
</div>
</template>
<script>
export default {
name: 'TitleBox',
};
</script>
<style>
.title-text{
font-size:18px
}
</style>
擴(kuò)展名為 vue
的文件會被打包工具編譯成標(biāo)準(zhǔn) js
文件以供瀏覽器執(zhí)行,在編譯時 <template>
模板的內(nèi)容會被轉(zhuǎn)換為 render
函數(shù)调违,換句話說 <template>
的內(nèi)容只是一個配置參數(shù)窟哺,Vue 通過這種類似于 HTML 的結(jié)構(gòu)來生成渲染方法,最后通過執(zhí)行渲染方法來初始化一個真正的頁面技肩。當(dāng)然對于復(fù)雜的需求我們也可以不用模板且轨,直接編寫 render
函數(shù)。
類似的還有 data
屬性虚婿,我們通常使用這樣的格式來定義 data
旋奢。
data() {
return {
commonData,
layout,
isShow: true,
isLoading: false
};
}
事實(shí)上這只是一個配置選項(xiàng),編譯時 Vue 會根據(jù)我們傳入的選項(xiàng)來生成真正的 data
實(shí)例然痊,其中的每個屬性都綁定了 getter
至朗、setter
方法,具備響應(yīng)式特性剧浸。這就是為什么需要顯式的定義 data
屬性锹引。
默認(rèn)情況下 data
內(nèi)的屬性會被 Vue 實(shí)例代理(Vue 實(shí)例的同名屬性指向 data
對象的屬性),如果某些屬性不想被 Vue 代理可以在屬性名稱前面加上 '$'
或 '_'
唆香,這樣就只能通過 Vue.$data._someProp
來訪問嫌变。
在實(shí)例化一個 Vue 對象時會經(jīng)歷那些階段呢?通俗的說會有兩個階段:一是生成 data
袋马,二是掛載 template
初澎,也就是 MVVM 中的 VM(view-model)。
生成 data
被稱作 create
虑凛,掛載 template
被稱作 mount
碑宴,兩個階段的前后分別對應(yīng)著兩組生命周期節(jié)點(diǎn),也就是 beforeCreate
桑谍、created
以及 beforeMound
延柠、mounded
。
有生則有滅锣披,銷毀響應(yīng)式屬性贞间,解除綁定事件的過程被稱作 destroy
,前后也分別對應(yīng)著 beforeDestroy
和 destroyed
節(jié)點(diǎn)雹仿。
響應(yīng)式屬性的變化會觸發(fā)視圖的更新增热,這個更新的過程被稱作 update
,前后自然也對應(yīng)著 beforeUpdate
胧辽、updated
兩個節(jié)點(diǎn)峻仇。數(shù)據(jù)與視圖綁定是 VM 框架提供的核心功能,也正是所謂的數(shù)據(jù)驅(qū)動邑商,數(shù)據(jù)驅(qū)動和事件驅(qū)動的差異有點(diǎn)類似于查詢和中斷的區(qū)別摄咆。
組件是一個封閉的環(huán)境凡蚜,除非通過生命周期節(jié)點(diǎn)來探測,不然操作內(nèi)部數(shù)據(jù)的進(jìn)度是無法獲知的吭从,換句話說我們從組件外部訪問 data
數(shù)據(jù)時朝蜘,無法確定它是更新前還是更新后的,尤其在通過異步方式請求后端數(shù)據(jù)時涩金,這個問題就更加明顯谱醇。因此官方不建議通過 $parent
、$children
或 $refs
等方式強(qiáng)行獲取數(shù)據(jù)步做,而是建議在數(shù)據(jù)狀態(tài)可控時通過事件觸發(fā)來回傳數(shù)據(jù)($emit枣抱、$on
)。
常用的模板語法
- 大胡子語法(雙大括號)可以方便的在 HTML 元素內(nèi)部(innerHTML)插入文本辆床。
<span> {{ status ? '有效' : '無效' }} </span>
- 設(shè)置模板標(biāo)簽屬性可以直接用
<span prop="text"></span>
的格式書寫,如果需要為屬性綁定變量或表達(dá)式則需使用v-bind
指令:<span :prop="value"></span>
桅狠,沒錯讼载,冒號':'
正是v-bind
指令的縮寫,等同于<span v-bind:prop="value"></span>
中跌,有時我們需要綁定數(shù)值(Number
)咨堤,而非內(nèi)容為數(shù)字的字符串,v-bind
指令恰好可以區(qū)分兩者漩符。
// 后端發(fā)送的數(shù)據(jù)
requiredData: {cityId: 3}
// 模板綁定的數(shù)據(jù)
<ex-select v-model="cityId">
<ex-option :value="1">北京</option>
<ex-option :value="2">上海</option>
<ex-option :value="3">廣州</option>
// 如果不加 ':' 會因?yàn)?3 !== '3'而找不到匹配項(xiàng)
</ex-select>
- 另一個支持縮寫的指令是
v-on
一喘,可以用'@'
表示,比如<button @click="handleClick"></button>
嗜暴,指令較多時凸克,縮寫可以使代碼更清晰。
<ex-input
v-model="userName"
:placeholder="姓名"
:disabled="isDisabled"
:readonly="isReadonly"
@focus="handleFocus"
@input="handleInput"
@change="handleChange">
</ex-input>
- 控制流程的指令包括:
v-if
闷沥、v-else
萎战、v-else-if
和v-for
。
// 判斷單行或多行文本框
<input type="text" v-if="inputType==='singleLine'"></input>
<textarea v-else="inputType==='multiLine'"></textarea>
// v-for 除了可以生成列表舆逃,還可以用于通過 JSON 動態(tài)生成模板
let formConfig = [{
type: 'singleLine',
name: 'userName'
},{
type: 'singleLine',
name: 'birthday'
},{
type: 'multiLine',
name: 'comment'
}]
<label v-for="item in formConfig">
{{ item.name }}
<ex-input inputType="item.type"></ex-input>
</label>
- 計(jì)算屬性可以用于篩選或格式化數(shù)據(jù)蚂维,比如當(dāng)后端返回時間戳?xí)r,我們可通過計(jì)算屬性獲取指定格式的日期時間路狮。
data() {
return {
updateTime: 1490526754
}
}
computed: {
timeString: {
get () {
// Js默認(rèn)以毫秒為單位虫啥,需要進(jìn)行轉(zhuǎn)換
let timeStamp = new Date(this.updateTime * 1000)
return timeStamp.toLocaleString()
},
set (val) {
let timeStamp = Math.round(Date.getTime() / 1000)
this.updateTime = val || timeStamp
}
}
}
- 如何響應(yīng)式更新
data
中的數(shù)組?
有時我們需要在數(shù)據(jù)表格組件中顯示一組數(shù)據(jù)奄妨,后端返回給我們一個JSON
數(shù)組:
<ex-table
data="dataSource"
></ex-table>
...
data () {
return {
dataSource: [{
id: 1, name: lily, age: 21
},{
id: 2, name: terry, age: 23
},{
id: 3, name: dill, age: 26
}]
}
}
我們修改了其中的某一項(xiàng)涂籽,并通過下面的方式更新到數(shù)組中:
let modifiedRow = {id: 2, name: frank, age: 20}
// 視圖未發(fā)生更新
this.dataSource[1] = modifiedRow
我們會發(fā)現(xiàn),表格中顯示的數(shù)據(jù)并沒有改變展蒂,這是因?yàn)橹苯訉?shù)組中的元素賦值不會觸發(fā)Vue的響應(yīng)式更新又活,為了解決 Js 語言特性的限制苔咪,Vue 提供了一種變通的方法,可以使用 push()
柳骄、pop()
团赏、shift()
等函數(shù)來修改數(shù)組。
// 視圖響應(yīng)式更新
dataSource.splice(1, 1, modifiedRow)
除此之外我們也可以通過 Vue.set()
函數(shù)修改數(shù)組耐薯,比如:
Vue.set(dataSource, 1, modifiedRow)
- 通過
v-model
指令為表單元素綁定數(shù)據(jù)
表單元素不但可以顯示數(shù)據(jù)也可以修改數(shù)據(jù)舔清,我們當(dāng)然可以通過 :value="data"
來顯示數(shù)據(jù),并且通過 @input="data=$event.target.value"
來修改數(shù)據(jù)曲初,不過 Vue 為我們提供了一個更簡潔的語法糖体谒,直接使用 v-model="data"
即可同時實(shí)現(xiàn)兩者的功能。
其實(shí)臼婆,對于任何自定義組件只要我們實(shí)現(xiàn)了 value
屬性和 input
事件都可以使用 v-model
指令進(jìn)行數(shù)據(jù)綁定抒痒。如果實(shí)現(xiàn)了 change
事件也可以配合 v-model.lazy
來調(diào)用。
// ex-input.vue
<input
type="text"
v-if="inputType==='singleLine'"
:value="editValue"
@input="handelInput"
></input>
<textarea
v-else="inputType==='multiLine'"
:value="editValue"
@input="handelInput"
></textarea>
...
data() {
return {
// 獲取表單初始值
editValue: this.value
}
},
prop: {
// 定義value屬性
value:[String, Number]
},
watch: {
// 觀察并同步value屬性
value(val) {
this.editValue = val
}
},
methods: {
handelInput (event) {
this.editValue = event.target.value
// 實(shí)現(xiàn)input事件
this.$emit('input', this.editValue)
}
}
...
// 兩者是等價的颁褂,顯然 v-model 更簡潔一些
<ex-input v-model="data"></ex-input>
<ex-input :value="data" @input="data=arguments[0]"></ex-input>
(未完待續(xù)...)