注意:文中的 vm 為 var vm = new Vue()
,可以在內(nèi)外部通過(guò)vm
引用,也可以在內(nèi)部通過(guò)this
指向
內(nèi)在
當(dāng)你把一個(gè)普通的 JavaScript 對(duì)象傳入 Vue 實(shí)例作為 data
選項(xiàng),Vue 將遍歷此對(duì)象所有的屬性荚板,并使用 Object.defineProperty
把這些屬性全部轉(zhuǎn)為 getter/setter
戴涝。
-
Object.defineProperty
是 ES5 中一個(gè)無(wú)法 shim 的特性,這也就是 Vue 僅支持IE9及以上版本瀏覽器的原因斋竞。 - 因此初始化實(shí)例時(shí)不在data中的屬性不會(huì)自動(dòng)轉(zhuǎn)換為響應(yīng)式倔约。且Vue 不允許動(dòng)態(tài)添加根級(jí)響應(yīng)式屬性。在初始化實(shí)例前應(yīng)聲明所有根級(jí)響應(yīng)式屬性坝初,即使為空浸剩。
Vue 在更新 DOM 時(shí)是異步執(zhí)行的。在每一個(gè)事件循環(huán)“tick”中鳄袍,Vue 刷新隊(duì)列并執(zhí)行實(shí)際 (已去重的) 工作绢要。Vue 在內(nèi)部對(duì)異步隊(duì)列嘗試使用原生的 Promise.then、MutationObserver 和 setImmediate拗小,如果執(zhí)行環(huán)境不支持重罪,則會(huì)采用 setTimeout(fn, 0) 代替。為了在數(shù)據(jù)更新后等待dom也更新完成哀九,可以使用Vue.nextTick(callback)
或vm.$nextTick()
指令 (Directives)
通常帶有 v- 前綴,通過(guò):
傳入?yún)?shù) , 通過(guò).
添加修飾符 , 其值(如有)應(yīng)為單個(gè) JavaScript 表達(dá)式剿配。(且可訪問(wèn)到Date
,Math
等特定的全局變量)指令的職責(zé)是,將表達(dá)式值的變化更新作用于 DOM阅束。不同于angular.js,在vue中指令和組件是完全不同的兩個(gè)概念呼胚。
- v-text 更新元素的 textContent。
- v-once 僅進(jìn)行首次插值
- v-show
- v-if / v-else-if / v-else
- v-for
- v-model
- v-html 請(qǐng)勿對(duì)用戶(hù)提供的內(nèi)容使用該指令,易導(dǎo)致xss攻擊
- v-slot 提供具名插槽或需要接收 prop 的插槽息裸。
- v-bind 操作dom屬性,可縮寫(xiě)為
:
砸讳。對(duì)于布爾型特性 ,由于只要出現(xiàn)就意味著值為 true,因此若為null
界牡、undefined
或false
簿寂,vue直接不渲染該屬性。 - v-on 監(jiān)聽(tīng)dom事件,可縮寫(xiě)為
@
宿亡。- 從 2.6.0 開(kāi)始常遂,可以用方括號(hào)傳入字符串或null作為指令參數(shù)。字符串不能有空格和引號(hào),且會(huì)自動(dòng)轉(zhuǎn)為小寫(xiě)挽荠。null可用于移除綁定克胳。
<a v-bind:[attributeName]="url"> ... </a>
<a v-on:[eventName]="doSomething"> ... </a>
- v-pre 對(duì)其中的
{{...}}
不進(jìn)行編譯 - v-cloak 這個(gè)屬性會(huì)保持在元素上直到關(guān)聯(lián)實(shí)例結(jié)束編譯,通常通過(guò)以下代碼實(shí)現(xiàn)防抖
[v-cloak] {
display: none;
}
...
<div v-cloak>
{{ message }}
</div>
計(jì)算屬性 和 偵聽(tīng)器
定義計(jì)算屬性 和 偵聽(tīng)器時(shí)圈匆,均不應(yīng)使用箭頭函數(shù)
計(jì)算屬性
計(jì)算屬性應(yīng)處于computed
中漠另,每當(dāng)計(jì)算屬性的相關(guān)響應(yīng)式依賴(lài)發(fā)生改變,則重新求值。
直接在模板語(yǔ)法中執(zhí)行函數(shù)也可以達(dá)成該效果,但需注意的是,函數(shù)每當(dāng)Vue對(duì)UI進(jìn)行update時(shí),都會(huì)重新執(zhí)行,因此性能開(kāi)銷(xiāo)會(huì)大于計(jì)算屬性跃赚。好處在于非響應(yīng)式依賴(lài)變更時(shí),函數(shù)值也會(huì)隨著頁(yè)面渲染而更新笆搓。
頁(yè)面第一次加載時(shí),兩個(gè)值相同性湿。
若str
發(fā)生更新,兩值同步更新。
若trigger1
更新,此時(shí)頁(yè)面重新渲染,{{computedFun()}}
更新,而{{computedData}}
不變满败。
若trigger2
更新,兩值都不變肤频。
{{computedData}}
{{computedFun()}}
{{trigger1}}
data:{
str : "當(dāng)前時(shí)間是:",
trigger1 : false,
trigger2 : false
},
computed: {
computedData: function () {
return this.str + new Date()
},
computedData2: vm => vm.str + new Date()
},
methods: {
computedFun(){
return this.str + new Date()
}
}
偵聽(tīng)器
偵聽(tīng)器可以達(dá)到與計(jì)算屬性相同的效果
需要監(jiān)聽(tīng)對(duì)象某個(gè)屬性時(shí),可以直接將對(duì)象.屬性
作為key算墨,或?qū)?code>deep設(shè)為true
watch: {
str: function (val,oldVal) {
this.watchedData = val + new Date()
},
str2: "someMethod",
"obj.key": function (val,oldVal) {
...
},
obj2: {
handler: "someMethod",
deep: true,//該回調(diào)會(huì)在被偵聽(tīng)的對(duì)象的任何 property 改變時(shí)觸發(fā)宵荒,不論嵌套多深
immediate: true//偵聽(tīng)綁定后(created之前)立刻生效,此時(shí)old值為undefined净嘀,新值為data中值
}
}
偵聽(tīng)器每次只能偵聽(tīng)一個(gè)值,如果需要同時(shí)偵聽(tīng)多個(gè),可配合computed
使用
computed: {
tempData: function () {
const { param1 , param2 } = this;
return { param1 , param2 }
}
},
watch: {
tempData: function (val) {
...
}
}
計(jì)算屬性的getter和setter
計(jì)算屬性默認(rèn)為getter方法,也可以給予一個(gè)包含get和set方法的對(duì)象报咳,當(dāng)主動(dòng)設(shè)置計(jì)算屬性值時(shí)就會(huì)觸發(fā)setter
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
Class與Style
class有兩種綁定方式
- 對(duì)象語(yǔ)法
:class="{ 'className' : true , 'className2' : false}"
(值為 truthy 即可,不一定需要為true) - 數(shù)組語(yǔ)法
:class="[ 'className1' , 'className2' ]"
注:對(duì)自定義添加的class,和該組件本身根元素的class,會(huì)取并集
style也有兩種綁定方式
- 對(duì)象語(yǔ)法
:style="{ 'background-color' : 'red', fontSize: 15 + 'px' }"
- 數(shù)組語(yǔ)法
:style="[{ 'background-color' : 'red' }],[{ fontSize: 15 + 'px' }]"
注:對(duì)需要加瀏覽器前綴的CSS屬性,vue會(huì)自動(dòng)檢測(cè)并添加,如transform
條件渲染
值為 truthy 即可,不一定需要為true
v-if / v-else-if / v-else
- 用key管理可復(fù)用的元素
- 可以用template當(dāng)做不可見(jiàn)的包裹元素,并在上面使用 v-if挖藏。
<template v-if="loginType === 'username'">
<label>Username</label>
<input key="username-input">
</template>
<template v-else>
<label>Email</label>
<input key="email-input">
</template>
注:不要把 v-if 和 v-for 同時(shí)用在同一個(gè)元素上少孝。(因 Vue 處理指令時(shí),v-for 比 v-if 具有更高的優(yōu)先級(jí)熬苍,因此每當(dāng)頁(yè)面渲染時(shí)不管數(shù)組是否發(fā)生變化都進(jìn)行了一次map稍走,不利于性能。)
v-show
v-show不支持template, 有較高的初始渲染開(kāi)銷(xiāo)和較低的切換開(kāi)銷(xiāo)柴底。
列表渲染
- 支持 (均可以為計(jì)算屬性或一個(gè)方法的返回值)
- 數(shù)組
- 對(duì)象
- 整數(shù)(會(huì)把模板重復(fù)對(duì)應(yīng)次數(shù))
- 建議使用key追蹤每個(gè)節(jié)點(diǎn)的身份
- 類(lèi)似
v-if
也可以用<template>
來(lái)循環(huán)渲染一段包含多個(gè)元素的內(nèi)容尤筐。
v-for="item in items" 或 v-for="item of items"
v-for="(item, index) in items"
v-for="(value, name, index) in object"
通過(guò)以下方式變更數(shù)組/對(duì)象無(wú)法觸發(fā)視圖更新
- 利用索引直接設(shè)置一個(gè)項(xiàng)時(shí)矩欠,例如:vm.items[index] = newValue
- 修改數(shù)組的長(zhǎng)度時(shí),例如:vm.items.length = newLength
- 對(duì)象屬性的新增或刪除
- 利用 Object.assign() 或 _.extend() 直接賦值
可通過(guò)以下方法解決
Vue.set(vm.target, attrToChange, newValue)
vm.$set(vm.target, attrToChange, newValue)
數(shù)組也可以通過(guò)splice
方法解決
vm.items.splice(indexOfItem, 1, newValue)
vm.items.splice(newLength)
另外如使用Object.assign()
或 _.extend()
時(shí),參考如下
Object.assign(vm.userProfile, {age: 27}) //無(wú)效
vm.userProfile = Object.assign({}, vm.userProfile, {age: 27}) //有效
組件列表
- 組件上使用
v-for
時(shí),必須傳入key
- 迭代數(shù)據(jù)不會(huì)自動(dòng)傳入組件,需要依賴(lài)prop
<my-component
v-for="(item, index) in items"
v-bind:item="item"
v-bind:index="index"
v-bind:key="item.id"
></my-component>
事件處理
- 通過(guò)
$event
可以把原生DOM事件傳入方法
事件修飾符
修飾符可以串聯(lián),且其順序決定了邏輯代碼的順序
- .stop 阻止繼續(xù)傳播
- .prevent 阻止默認(rèn)事件
- .capture 添加事件監(jiān)聽(tīng)器時(shí)使用事件捕獲模式
- .self 僅當(dāng) event.target 是自身時(shí)觸發(fā),不會(huì)被子元素觸發(fā)
- .once 僅執(zhí)行一次
- .passive (2.3.0 新增) 對(duì)應(yīng)
addEventListener
中的passive
選項(xiàng),可以提升移動(dòng)端的性能响蓉。會(huì)覆蓋.prevent
谆趾。
按鍵修飾符
可以將 KeyboardEvent.key
暴露的任意有效按鍵名轉(zhuǎn)換為 kebab-case 來(lái)作為修飾符犹菇。如.enter , .tab , .delete (捕獲“刪除”和“退格”鍵) , .esc , .space , .up , .down , .left , .right, .ctrl, .alt, .shift, .meta(windows鍵或command鍵)
以及鼠標(biāo)按鍵.right , .left, .middle
<input v-on:keyup.enter="submit">
<input v-on:keyup.page-down="onPageDown">
也可以通過(guò)config.keyCodes
自定義按鍵修飾符
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
- 2.5.0 新增
.exact
修飾符
允許控制由精確的系統(tǒng)修飾符組合觸發(fā)的事件
<!-- 有且只有 Ctrl 被按下的時(shí)候才觸發(fā) -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 沒(méi)有任何系統(tǒng)修飾符被按下的時(shí)候才觸發(fā) -->
<button @click.exact="onClick">A</button>
表單輸入
v-model 在內(nèi)部為不同的輸入元素使用不同的屬性并拋出不同的事件:
- text 和 textarea 元素使用 value 屬性和 input 事件妹懒;
- checkbox 和 radio 使用 checked 屬性和 change 事件;
- select 字段將 value 作為 prop 并將 change 作為事件野哭。
通常情況下v-model 綁定的值是靜態(tài)字符串或布爾值在塔,但如果使用v-bind:value
則也可以傳入其他類(lèi)型
復(fù)選框
單個(gè)復(fù)選框可綁定到布爾值,或通過(guò)true-value
和false-value
綁定其他屬性拨黔。多個(gè)復(fù)選框時(shí)則可通過(guò)value綁定到數(shù)組
<input type="checkbox" id="checkbox" v-model="checked">
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
...
checked : false
toggle : "no"
checkedNames: []
修飾符
- .lazy 在“change”時(shí)而非“input”時(shí)更新
- .number 將輸入值轉(zhuǎn)為number類(lèi)型
- .trim 自動(dòng)過(guò)濾收尾空白字符
生命周期
new Vue()
時(shí)依次執(zhí)行breforeCreate
蛔溃、created
、beforeMount
篱蝇、mounted
-
breforeCreate
此時(shí)不存在this.$el
贺待,data
和methods
也都拿不到 -
created
、
此時(shí)不存在this.$el
零截,但可以拿到data
和methods
麸塞。獲取數(shù)據(jù)可以放在該階段 -
beforeMount
必須有el: '#app'
才會(huì)觸發(fā),此時(shí)this.$el
指向html中書(shū)寫(xiě)的內(nèi)容涧衙,但并未經(jīng)過(guò)vue處理哪工,如<div>{{loading}}</div>
-
mounted
必須有el: '#app'
才會(huì)觸發(fā)奥此,此時(shí)this.$el
指向渲染后的模板內(nèi)容,如<div>true</div>
beforeCreate ->inject -> Props -> Methods -> Data -> Computed -> Watch ->provide-> created