此篇是關於 Vue 的總結。Js 的總結請見前一篇:Vue + ElementUI 後臺管理系統項目心得(一)javascript
話說過完年回來,彷彿一晚上之間身邊的人都在談論 Vue,相關的組件也如雨後春筍通常涌現出來,好比大名鼎鼎的 Element UI
、iView
還有不久前剛發佈的 ATUI
,這些組件庫雖然實現方式和接口格式有所不一樣,但大都界面美觀,體驗流暢,能夠說和 Vue 框架提供的良好性能是密不可分的。css
Vue 是一個上手簡單,卻富有內涵的框架,既能夠像使用 jQuery
同樣簡單地經過 <script>
標籤引入,也支持經過打包工具構建。html
// 一個簡單的title.vue模板文件,同時具有了Web三要素:結構層、表現層和行爲層。
<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>複製代碼
擴展名爲 vue
的文件會被打包工具編譯成標準 js
文件以供瀏覽器執行,在編譯時 <template>
模板的內容會被轉換爲 render
函數,換句話說 <template>
的內容只是一個配置參數,Vue 經過這種相似於 HTML 的結構來生成渲染方法,最後經過執行渲染方法來初始化一個真正的頁面。固然對於複雜的需求咱們也能夠不用模板,直接編寫 render
函數。vue
相似的還有 data
屬性,咱們一般使用這樣的格式來定義 data
。java
data() {
return {
commonData,
layout,
isShow: true,
isLoading: false
};
}複製代碼
事實上這只是一個配置選項,編譯時 Vue 會根據咱們傳入的選項來生成真正的 data
實例,其中的每一個屬性都綁定了 getter
、setter
方法,具有響應式特性。這就是爲何須要顯式的定義 data
屬性。後端
默認狀況下 data
內的屬性會被 Vue 實例代理(Vue 實例的同名屬性指向 data
對象的屬性),若是某些屬性不想被 Vue 代理能夠在屬性名稱前面加上 '$'
或 '_'
,這樣就只能經過 Vue.$data._someProp
來訪問。數組
在實例化一個 Vue 對象時會經歷那些階段呢?通俗的說會有兩個階段:一是生成 data
,二是掛載 template
,也就是 MVVM 中的 VM(view-model)。瀏覽器
生成 data
被稱做 create
,掛載 template
被稱做 mount
,兩個階段的先後分別對應着兩組生命週期節點,也就是 beforeCreate
、created
以及 beforeMound
、mounded
。框架
有生則有滅,銷燬響應式屬性,解除綁定事件的過程被稱做 destroy
,先後也分別對應着 beforeDestroy
和 destroyed
節點。異步
響應式屬性的變化會觸發視圖的更新,這個更新的過程被稱做 update
,先後天然也對應着 beforeUpdate
、updated
兩個節點。數據與視圖綁定是 VM 框架提供的核心功能,也正是所謂的數據驅動,數據驅動和事件驅動的差別有點相似於查詢和中斷的區別。
組件是一個封閉的環境,除非經過生命週期節點來探測,否則操做內部數據的進度是沒法獲知的,換句話說咱們從組件外部訪問 data
數據時,沒法肯定它是更新前仍是更新後的,尤爲在經過異步方式請求後端數據時,這個問題就更加明顯。所以官方不建議經過 $parent
、$children
或 $refs
等方式強行獲取數據,而是建議在數據狀態可控時經過事件觸發來回傳數據($emit、$on
)。
<span> {{ status ? '有效' : '無效' }} </span>複製代碼
<span prop="text"></span>
的格式書寫,若是須要爲屬性綁定變量或表達式則需使用 v-bind
指令:<span :prop="value"></span>
,沒錯,冒號 ':'
正是 v-bind
指令的縮寫,等同於 <span v-bind:prop="value"></span>
,有時咱們須要綁定數值(Number
),而非內容爲數字的字符串,v-bind
指令剛好能夠區分二者。// 後端發送的數據
requiredData: {cityId: 3}
// 模板綁定的數據
<ex-select v-model="cityId">
<ex-option :value="1">北京</option>
<ex-option :value="2">上海</option>
<ex-option :value="3">廣州</option>
// 若是不加 ':' 會由於 3 !== '3'而找不到匹配項
</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 動態生成模板
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>複製代碼
data() {
return {
updateTime: 1490526754
}
}
computed: {
timeString: {
get () {
// Js默認以毫秒爲單位,須要進行轉換
let timeStamp = new Date(this.updateTime * 1000)
return timeStamp.toLocaleString()
},
set (val) {
let timeStamp = Math.round(Date.getTime() / 1000)
this.updateTime = val || timeStamp
}
}
}複製代碼
data
中的數組?JSON
數組:<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 }] } }複製代碼
咱們修改了其中的某一項,並經過下面的方式更新到數組中:
let modifiedRow = {id: 2, name: frank, age: 20}
// 視圖未發生更新
this.dataSource[1] = modifiedRow複製代碼
咱們會發現,表格中顯示的數據並無改變,這是由於直接對數組中的元素賦值不會觸發Vue的響應式更新,爲了解決 Js 語言特性的限制,Vue 提供了一種變通的方法,可使用 push()
、pop()
、shift()
等函數來修改數組。
// 視圖響應式更新
dataSource.splice(1, 1, modifiedRow)複製代碼
除此以外咱們也能夠經過 Vue.set()
函數修改數組,好比:
Vue.set(dataSource, 1, modifiedRow)複製代碼
v-model
指令爲表單元素綁定數據表單元素不但能夠顯示數據也能夠修改數據,咱們固然能夠經過 :value="data"
來顯示數據,而且經過 @input="data=$event.target.value"
來修改數據,不過 Vue 爲咱們提供了一個更簡潔的語法糖,直接使用 v-model="data"
便可同時實現二者的功能。
其實,對於任何自定義組件只要咱們實現了 value
屬性和 input
事件均可以使用 v-model
指令進行數據綁定。若是實現了 change
事件也能夠配合 v-model.lazy
來調用。
// 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
// 實現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>複製代碼
(未完待續...)