vue概述sd
在官方文檔中,有一句話對Vue的定位說的很明確:
Vue.js 的核心是一個允許采用簡潔的模板語法來聲明式地將數(shù)據(jù)渲染進 DOM 的系統(tǒng)
Vue在我的理解下辕宏,其實很像mvvm架構(gòu)中畜晰,對vm的實行。在mvvm架構(gòu)中瑞筐,viewModel是負責把view和model關聯(lián)起來凄鼻,把model的數(shù)據(jù)同步到view顯示出來,把view的修改同步回model聚假。在Vue的data屬性中可設定相關變量块蚌,并把這些變量和Dom進行關聯(lián),達到修改data中屬性即可修改Dom的功能 ( model(data) --> Vue --> view(dom) )膘格。在Dom上峭范,通過觸發(fā)綁定方法,對相關數(shù)據(jù)進行修改 ( view(dom) --> Vue --> model(data) )瘪贱。按這個思路來理解Vue纱控,可以大概猜想出Vue有些功能為什么要被設計出來。
- 插值:快速實現(xiàn)data和view的快速綁定菜秦,
- 指令:對插值的補充甜害,作用于模板上,用來實現(xiàn)模板的重復生成(v-for)球昨,動態(tài)顯示(v-show, v-if)尔店,屬性綁定(v-bind),事件綁定(v-on),對表單的增強(v-model)
- 計算屬性和觀察屬性:對插值和指令的補充嚣州,動態(tài)響應更新數(shù)據(jù)達到動態(tài)更新Dom的功效
- 過濾:對插值和v-bind指令的補充鲫售,對要綁定到Dom上的數(shù)據(jù)進行過濾
- 組件:Vue最強大的功能,對viewModel的實現(xiàn)该肴,template就是view層情竹,script就是model層
這些內(nèi)容組成了Vue的骨架,掌握以上內(nèi)容基本就能上手開發(fā)沙庐。下面我就利用上一章的例子把這些內(nèi)容詳細的介紹下(我按照我的理解打亂了官方的介紹順序)
1. 插值
<template>
<div class="wrap">
<p>{{info}}</p>
</div>
</template>
<script>
export default {
data () {
return {
info: 'Hello world!'
}
}
}
</script>
文本插值
處于data中返回值的info就是一個文本插值鲤妥,這時如果修改info的值,對應DOM(p標簽)的就會發(fā)生改變
上面data必須是函數(shù)的寫法拱雏,是因為這是在一個組件內(nèi)部棉安,如果使用對象形式的寫法,這個組件在經(jīng)過多個實例化后铸抑,實際上是在共享一個data對象贡耽,更改任一組件data中的值,就會影響所有組件鹊汛,所以組件內(nèi)的data必須是函數(shù)蒲赂,這樣每個組件就形成獨立的函數(shù)作用域,彼此不沖突刁憋。
屬性插值
如果想把data中的值綁定成為html元素的屬性滥嘴,需要使用v-bind指令(簡寫方式是 : ),代碼改造如下:
<p v-bind:title="info">{{info}}</p>
這個綁定值可以是普通的html屬性至耻,也可以是自定義屬性
<p v-bind:data-cusData="info">{{info}}</p>
這時如果看最終渲染的頁面若皱,其效果是忽略cusData的大寫,只顯示為cusdata
<p data-cusdata="Hello vue!">Hello vue!</p>
如果這里是設置常用的class,id,title屬性是沒什么問題尘颓,但如果是自定義屬性比如data-cusData這種類型的數(shù)據(jù)走触,就會被強制轉(zhuǎn)為data-cusdata
如果要綁定多個屬性值可以使用對象的形式
<p v-bind='{id: elemId, class: elemClass, "data-cusData": cusData}'>{{info}}</p>
Data中設置修改如下
data () {
return {
info: 'Hello vue!',
elemId: 'pId',
elemClass: 'pClass',
cusData: 'hello world'
}
}
因為class和style是我們常用的屬性值,Vue針對這兩個屬性做了特殊處理
2. 樣式
1):class綁定對象語法
改造代碼如下
<p class=‘static’ :class='{red: redFlag, font: fontFlag }'>{{info}}</p>
:class是v-bind:class的簡寫
對應data修改如下:
{
...
redFlag: true,
fontFlag: false
}
頁面渲染結(jié)果如下:
<p class="static red">Hello vue!</p>
如例子顯示疤苹,綁定對象的形式可以動態(tài)切換多個class互广,同時也支持與普通class共存
當綁定對象要進行多個class值的設定,沿用上面的寫法會顯得繁瑣卧土,我們可以把綁定的對象換成一個計算屬性惫皱,在計算屬性中動態(tài)的設定返回值。
<p class='static' :class='classObj'>{{info}}</p>
在計算屬性中設定相關值
computed: {
classObj () {
let classStr = '';
if (this.redFlag) {
classStr += 'red';
}
if (this.fontFlag) {
classStr += 'font';
}
return classStr;
}
}
渲染結(jié)果如上尤莺,除了上面的寫法逸吵,也可以結(jié)合下面介紹的綁定數(shù)組語法,把上面的例子再簡化些
<p :class='[classObj, "static"]'>{{info}}</p>
2) :class綁定數(shù)組語法
代碼如下:
<p :class="[basicClass, redClass]">{{info}}</p>
data下數(shù)據(jù)修改如下:
{
...
basicClass: 'f20 mb20',
redClass: 'red'
}
這樣最終渲染如下:
<p class="f20 mb20 red">Hello vue!</p>
在數(shù)組語法中缝裁,可以使用三元運算符控制某個元素class的添加和隱藏
代碼改造如下:
<p :class="[showInfo ? basicClass : '', redClass]">{{info}}</p>
data數(shù)據(jù)修改如下:
{
...
showInfo: false,
...
}
這時渲染的最早結(jié)果如下:
<p class="red">Hello vue!</p>
如果把showInfo設為true,渲染結(jié)果和上例一致
官方文檔這里還介紹了對組件的class綁定處理,不過我覺得這樣做其實會破壞組件的封裝型捷绑,就算要添加或者移除某個class韩脑,最好還是通過props傳值在組件內(nèi)部自行處理
3) :style綁定對象語法
:style的綁定對象語法和:class綁定對象語法使用方法一樣,只是在寫css屬性名要注意下
<p :style='{color: redColor, "font-size": fontSize, backgroundColor: bgColor }'>{{info}}</p>
data數(shù)據(jù)修改如下:
{
...
redColor: 'red',
fontSize: '16px',
bgColor: '#FF0'
...
}
如例css的屬性名粹污,可以改寫成駝峰形式(backgroundColor)段多,或者使用引號包裹起來("font-size")
當使用對象語法進行多個css屬性設置時,可以使用計算屬性進行綁定
<p :style='styleObj'>{{info}}</p>
計算屬性設置如下
computed: {
styleObj () {
return `color: ${this.redColor}; fontSize: ${this.fontSize}; backgroundColor: ${this.bgColor}`;
}
}
渲染結(jié)果如下:
<p style="color: red; font-size: 16px; background-color: rgb(255, 255, 0);">Hello vue!</p>
上面設定樣式的方式如果只是綁定單個對象是沒問題的壮吩,但如果要使用數(shù)組的形式綁定多個對象就無法生效(解決方法參看下面)进苍。
4) :style綁定數(shù)組語法
使用:class綁定數(shù)組使用方法見下例:
<p :style='[colorStyle, fontStyle, backgroundColor]'>{{info}}</p>
這個時候要保證對應數(shù)組對象是對象的形式(上例是字符串形式):
這個例子中綁定對象的值分別在data和計算屬性中設定,只是做演示鸭叙,表示這個綁定值觉啊,可以是不同的來源值進行混合
在data中設定colorStyle
{
...
colorStyle: {
color: 'red'
}
...
}
在計算屬性中設定fontStyle和backgroundColor
computed: {
fontStyle () {
return {fontSize: this.fontSize}
},
backgroundColor () {
return {backgroundColor: this.bgColor}
}
}
這時的渲染結(jié)果和上例是一致的,但如果你把其中一個值沈贝,改成字符串形式
fontStyle () {
return `fontSize: ${this.fontSize};`
}
這時你會發(fā)現(xiàn)Vue會忽略當前值的設定杠人,所以在使用:style形式時,最好按對象形式返還設定的style宋下。
3.指令
我對指令的理解就是:指令是使模板具備了邏輯處理的能力嗡善,是對插值的一種補充,因為指令的存在才使得數(shù)據(jù)層和Dom層具備了相互綁定的能力学歧。
按官方api罩引,vue的指令如下:
v-text
v-html
v-show
v-if
v-else
v-else-if
v-for
v-on
v-bind
v-model
v-pre
v-cloak
v-once
1)v-text和v-bind
v-text實現(xiàn)文本綁定的能力,期望值是string
<p v-text="info"></p>
<p>{{info}}</p>
上面兩種寫法渲染后的結(jié)果一致,通常我們會使用第二種寫法枝笨,比較簡潔袁铐。這個指令期望的值是string,但如果綁定的值是一個對象伺帘,就會原樣把對象輸出昭躺。
<p>{{infoObj}}</p>
在data中設定一個infoObj
{
...
infoObj: {
msg: 'Hello vue!'
}
...
}
這時頁面渲染為
<p>{
"msg": "Hello vue!"
}</p>
如果你進行下面的設定
infoObj: true, // => true
或
infoObj: 3 > 2, // => true
或
infoObj: Math.random(), // => 渲染為一個不確定的隨機數(shù)
或
infoObj: 2 + 3, // => 5
所以這個指令會對傳入的值進行一個轉(zhuǎn)換,轉(zhuǎn)換成string伪嫁。事例中該指令的綁定值领炫,我只使用了data下的值,但實際上這個值還可以是計算屬性张咳。
computed: {
infoObj () {
return 'Hello vue by computed!'
}
}
對頁面進行渲染時帝洪,頁面的展示數(shù)據(jù)分為靜態(tài)數(shù)據(jù)和動態(tài)數(shù)據(jù),一般情況下靜態(tài)數(shù)據(jù)存放在data屬性下脚猾,動態(tài)數(shù)據(jù)通過計算屬性進行返回(上例只是個樣式葱峡,正常情況下計算屬性會包含相關邏輯處理,相關會在計算屬性那部分講解龙助,這里就不展開了)
v-bind用來動態(tài)的綁定一個或者多個屬性
在屬性插值部分已經(jīng)對v-bind指令做了比較詳細的介紹砰奕,有一些特殊點要特別說下:
綁定值可以是一個表達式
<p v-bind:title="info + ' 這時行內(nèi)添加的信息'">{{info}}</p>
這時頁面渲染結(jié)果為
<p title="Hello vue! 這時行內(nèi)添加的信息">Hello vue!</p>
這是一個比較有用的特性,在開發(fā)過程中我們很容易碰到根據(jù)數(shù)據(jù)的不同展示不同的樣式(比如符合某個條件時文案顏色變紅)
<p :class='[this.login ? "red" : "", "static", elemClass]'>{{info}}</p>
在data中我們假定一個login的字段
{
...
login: true
...
}
這時頁面就會渲染為
<p class="red static pClass">Hello vue!</p>
如例中假設,比如我現(xiàn)在有個接口返回用戶是否登陸军援,拿到接口返回數(shù)據(jù)仅淑,我們就可以根據(jù)接口返回的相關字段,動態(tài)的設定某一處的class胸哥。
通過修飾符.prop綁定DOM屬性
如果在綁定屬性后使用.prop修飾符涯竟,會忽略其他對該值的設定,強制使用設定的屬性值
<p class="testProp" v-bind:text-content.prop="info" v-bind:className.prop="elemId">測試數(shù)據(jù)</p>
這時頁面會渲染為
<p class="pId">Hello vue!</p>
如果刪掉一個prop值
<p class="testProp" v-bind:text-content="info" v-bind:className.prop="elemId">測試數(shù)據(jù)</p>
對應的綁定值就會變成一個普通的屬性值
<p class="pId" text-content="Hello vue!">測試數(shù)據(jù)</p>
2) v-html
該指令是用來直接輸出HTML內(nèi)容
<div v-html="html"></div>
在data中設定如下值
{
...
html: '<p>Hello vue!</p>',
...
}
這時頁面的渲染結(jié)果為
<div><p>Hello vue!</p></div>
如果使用v-text會原樣把字符串內(nèi)容輸出
<div v-text="html"></div>
渲染為
<div><p>Hello vue!</p></div>
在官方文檔中強調(diào)這種寫法很容易引起XSS攻擊空厌,不能把這個能力開放給普通用戶庐船,在實際開發(fā)中,我也沒碰到什么地方需要使用該指令嘲更。筐钟。。
3)v-show
根據(jù)表達式之真假值(這個值可以是data中的值哮内,也可以是計算屬性盗棵,后續(xù)不再贅述),切換元素的 display CSS 屬性北发。
<p v-show="showFlag">{{info}}</p>
在data中設定showFlag的值
{
...
showFlag: true,
...
}
這時頁面渲染為
<p>Hello vue!</p>
如果showFlag設為false纹因,頁面渲染為
<p style="display: none;">Hello vue!</p>
v-show指令使用時有如下內(nèi)容需要注意:
- v-show不支持<template>元素,因為template標簽的元素的內(nèi)容不會被渲染琳拨,所以對該標簽使用v-show去改變其的display屬性是沒有意義的瞭恰。
- v-show不支持和v-else一起使用,v-show只管當前元素的顯示與否
4)v-if
該指令會根據(jù)表達式的值動態(tài)渲染元素狱庇。元素及其包含的指令/組件在切換期間被銷毀并重新構(gòu)建惊畏。如果是作用在<template>元素上,則其內(nèi)部元素內(nèi)容會根據(jù)表達式的值動態(tài)建立或者銷毀密任。(這點是與v-show的不同點颜启,v-show只是改變display的值,v-if則會進行動態(tài)的建立或者銷毀)
<template v-if="showFlag"><p>{{info}}</p></template>
渲染為
<p>Hello vue!</p>
5)v-else和v-else-if
對v-if的補充浪讳,必須緊跟著v-if之后缰盏,否則無法生效
<p v-if="type === 'A'">A</p>
<p v-else-if="type === 'B'">B</p>
<p v-else-if="type === 'C'">C</p>
<p v-else>D</p>
在data中設定type一個隨意的值
{
...
type: 'E',
...
}
這時頁面渲染為
<p>D</p>
由于v-if會對元素進行重建或者銷毀,而Vue在渲染時會盡可能復用已有元素淹遵,針對普通元素這個指令使用起來是沒問題的口猜,但針對一些表單元素就有問題了。
<template v-if="type === 'A'"><input placeholder="A"/></template>
<template v-else-if="type === 'B'"><input placeholder="B"/></template>
<template v-else-if="type === 'C'"><input placeholder="C"/></template>
<template v-else><input placeholder="D"/></template>
<button @click="changeType">切換Type的值</button>
@click是v-on:click的簡寫(這個是用來綁定事件)透揣,在methods中添加相關方法
methods: {
changeType () {
let [random, type] = [Math.random(), ''];
if (random > 0.8) {
type = 'A';
} else if (random > 0.6) {
type = 'B';
} else if (random > 0.2) {
type = 'C';
} else {
type = 'D';
}
this.type = type;
}
},
頁面渲染為
<input placeholder="D">
<button>切換Type的值</button>
點擊button济炎,會發(fā)現(xiàn)input元素的內(nèi)容會發(fā)生改變,但如果你向input輸入一個值辐真,這時你再點擊button须尚,雖然input元素會變崖堤,但是已經(jīng)輸入的內(nèi)容卻不會改變,類似的還有textarea標簽恨闪。
如果認為這是一個問題倘感,可以使用Vue提供的防重的方式,使用key添加一個唯一的關鍵值咙咽。做以下改造
<template v-if="type === 'A'"><input key="A" placeholder="A"/></template>
<template v-else-if="type === 'B'"><input key="B" placeholder="B"/></template>
<template v-else-if="type === 'C'"><input key="C" placeholder="C"/></template>
<template v-else><input key="D" placeholder="D"/></template>
<button @click="changeType">切換Type的值</button>
這時如果輸入內(nèi)容,再點擊切換input就會完全重新渲染淤年,不過之前輸入的內(nèi)容也會被清除
6)v-for
v-for指令根據(jù)一組數(shù)組的選項列表進行渲染钧敞,通常我們只會在需要展示列表的部分使用該指令。
數(shù)據(jù)源是一個對象組成的數(shù)組
<ul>
<li v-for="item in students">姓名:{{item.name}}--年齡:{{item.age}}</li>
</ul>
在data下設定students的值
{
...
students:[
{name:'Tom', age:24},
{name:'Jim', age:22},
{name:'Kate', age:21}
],
...
}
渲染結(jié)果為
<ul>
<li>姓名:Tom--年齡:24</li>
<li>姓名:Jim--年齡:22</li>
<li>姓名:Kate--年齡:21</li>
</ul>
從這個例子麸粮,我們可以看出該指令是在當前元素進行循環(huán)渲染溉苛,根據(jù)條件展示數(shù)據(jù),該指令還可以接受一個參數(shù)表示數(shù)組的排序(從0開始)
<ul>
<li v-for="(item, $index) in students">{{$index}}.姓名:{{item.name}}--年齡:{{item.age}}</li>
</ul>
渲染為
<ul>
<li>0.姓名:Tom--年齡:24</li>
<li>1.姓名:Jim--年齡:22</li>
<li>2.姓名:Kate--年齡:21</li>
</ul>
數(shù)據(jù)源是一個對象
<ul>
<li v-for="value in tomInfo">{{value}}</li>
</ul>
在data中添加相關數(shù)據(jù)
{
...
tomInfo:{
age: 24,
gender: 'man',
address: '北二環(huán)前門里'
},
...
}
渲染為
<ul>
<li>24</li>
<li>man</li>
<li>北二環(huán)前門里</li>
</ul>
此時如果指令接受的第二個參數(shù)表示的是對象key值
<ul>
<li v-for="(value, key) in tomInfo">{{key}} : {{value}}</li>
</ul>
渲染為
<ul>
<li>age : 24</li>
<li>gender : man</li>
<li>address : 北二環(huán)前門里</li>
</ul>
在數(shù)據(jù)源是對象的情況下弄诲,該指令還可以接受第三個參數(shù)愚战,表示序號
<ul>
<li v-for="(value, key, $index) in tomInfo">{{$index}}. {{key}} : {{value}}</li>
</ul>
渲染為
<ul>
<li>0\. age : 24</li>
<li>1\. gender : man</li>
<li>2\. address : 北二環(huán)前門里</li>
</ul>
上面是我們假定的一個例子,通常我們是從后端拿到數(shù)據(jù)然后再在前端展示齐遵,而后端給到前端的數(shù)據(jù)通常是按照JSON格式給出寂玲,key值都是英文,這時前端就要對key值進行一個轉(zhuǎn)為中文的操作梗摇,我們現(xiàn)在要對已經(jīng)處理過的數(shù)據(jù)在進行簡單處理(邏輯并不復雜)拓哟,這時我們就需要使用過濾器(本部分只簡單介紹)
在filters(這是組件內(nèi)的寫法)下添加相關過濾器
filters: {
keyCheck (val) {
let cnVal = '';
if (val === 'age') {
cnVal = '年齡';
} else if (val === 'gender') {
cnVal = '性別';
} else if (val === 'address') {
cnVal = '家庭住址';
}
return cnVal;
}
}
頁面內(nèi)容進行如下改造
<ul>
<li v-for="(value, key, $index) in tomInfo">{{$index}}. {{key | keyCheck}} : {{value}}</li>
</ul>
注意{{key | keyCheck}}就是過濾器的使用方法,頁面渲染為
<ul>
<li>0\. 年齡 : 24</li>
<li>1\. 性別 : man</li>
<li>2\. 家庭住址 : 北二環(huán)前門里</li>
</ul>
關于v-for使用:key提升性能的解釋
在Vue的官方文檔中介紹v-for指令時伶授,提到使用key值提升渲染性能断序,具體原因官方?jīng)]有詳細介紹,只說Vue在進行渲染時進行的是“就地復用”策略糜烹。如果數(shù)據(jù)項的順序被改變违诗,Vue 將不會移動 DOM 元素來匹配數(shù)據(jù)項的順序, 而是簡單復用此處每個元素疮蹦,并且確保它在特定索引下顯示已被渲染過的每個元素诸迟。
參考如下實例,有助于理解這段話:
<div v-for="(item, $index) in listInfo" :title="item.id">
<input :placeholder="item.value"/>
</div>
<button @click="addList">添加新的列表內(nèi)容</button>
在data和methods下添加如下內(nèi)容
{
...
listInfo: [
{id: 'listA', value: 'A'},
{id: 'listB', value: 'B'},
{id: 'listC', value: 'C'},
{id: 'listD', value: 'D'}
]
...
}
methods: {
addList () {
this.listInfo.splice(1, 0, {id: 'listE', value: 'E'})
}
},
這時頁面渲染為
<div title="listA"><input placeholder="A"></div>
<div title="listB"><input placeholder="B"></div>
<div title="listC"><input placeholder="C"></div>
<div title="listD"><input placeholder="D"></div>
<button>添加新的列表內(nèi)容</button>
如果在幾個輸入框中輸入隨意文字挚币,然后再點擊按鈕亮蒋,這時我們發(fā)現(xiàn)渲染結(jié)果為
<div title="listA"><input placeholder="A"></div>
<div title="listE"><input placeholder="E"></div>
<div title="listB"><input placeholder="B"></div>
<div title="listC"><input placeholder="C"></div>
<div title="listD"><input placeholder="D"></div>
<button>添加新的列表內(nèi)容</button>
渲染的信息如我們所預期的一致,但是我們剛剛輸入的文字輸入框卻沒有按預期的下移妆毕,比較明顯的被直接復用慎玖,這也就是官方文檔中提到的如果數(shù)據(jù)項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據(jù)項的順序笛粘,不過在這個例子中這種Vue的默認處理方式是不符合我們的預期趁怔,所以這時要使用key值來標記每個節(jié)點湿硝,方便Vue對數(shù)據(jù)進行重新排序
<div v-for="(item, $index) in listInfo" :title="item.id" :key="item.id">
<input :placeholder="item.value"/>
</div>
<button @click="addList">添加新的列表內(nèi)容</button>
渲染結(jié)果同上沒有變化,但是如果你這時再輸入框輸入文字润努,然后再點擊按鈕時关斜,Dom就會按預期的排序
在這里會有個容易忽略的問題,如果你把key的綁定值換成數(shù)組序號的$index值
:key="$index"
Vue會忽略這個key的設定铺浇,還是按照未設定key時的方式進行渲染痢畜,原因(以下是個人理解,可能根本原因并不是這樣)是此時key值綁定的是數(shù)組的序號值(數(shù)字是不可變值)鳍侣,雖然可以通過addList方法觸發(fā)listInfo值的更新丁稀,但是無法觸發(fā)key綁定值的更新,Vue會把新加的數(shù)據(jù)當作普通數(shù)據(jù)倚聚,采取"就地復用"的策略(也就是官方文檔中提到的確保它在特定索引下顯示已被渲染過的每個元素)线衫,直接更新Dom而不對Dom進行重新排序,所以我們做如下修改惑折,來驗證我們的想法
<div v-for="(item, $index) in listInfo" :title="list[$index]" :key="list[$index]">
<input :placeholder="item.value"/>
</div>
<button @click="addList">添加新的列表內(nèi)容</button>
在data中設定list值
{
...
list: [1, 2, 3, 4],
...
}
同時在修改addList方法授账,觸發(fā)list數(shù)組的更新
addList () {
this.listInfo.splice(1, 0, {id: 5, value: 'E'});
this.list.splice(1, 0, 5);
}
這時如果進行相關操作,就會發(fā)現(xiàn)和上面方法(:key="item.id")呈現(xiàn)一致惨驶,在上例中key的綁定值是一個數(shù)組對象白热,同時在addList方法中更新數(shù)組數(shù)據(jù)(如果不進行更新,而是在list中提前定義好敞咧,一樣無法觸發(fā)Dom的重新排序)
觸發(fā)v-for的數(shù)據(jù)更新
v-for的數(shù)據(jù)源如果是數(shù)組時棘捣,我們可以使用觸發(fā)數(shù)組更新的方法,來觸發(fā)v-for的重新渲染
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
copyWithin()
fill()
以上的方法都會觸發(fā)原始數(shù)組的更新休建,數(shù)組更新自然就會觸發(fā)v-for的重新渲染乍恐,數(shù)組的其他方法比如filter,concat测砂,slice茵烈,every,map砌些,find呜投,findIndex等方法都不回直接修改原始數(shù)組,數(shù)組不更新存璃,v-for也就不會重新渲染仑荐,如果需要對數(shù)組使用到非更新方法,可以把處理后的數(shù)組直接賦值給原始數(shù)組
其他特殊情況
Vue沒有實現(xiàn)對以下內(nèi)容變化的檢測(按官方說法是受javascript限制纵东,后續(xù)單獨講解):
檢測數(shù)組的變化
- 利用索引直接設置數(shù)組值:arr[0] = newValue;
- 修改數(shù)組長度:arr.length = newLength;
用下面例子演示解決方法:
<div v-for="(item, $index) in listInfo" :title="item.id" :key="item.id">
<input :placeholder="item.value"/>
</div>
<button @click="editList">修改list內(nèi)容</button>
在methods添加editList方法:
methods: {
editList () {
// this.listInfo[0] = {id:1, value:'AA'};
this.$set(this.listInfo, 0, {id:1, value:'AA'});
}
}
this.$set是在methods方法內(nèi)的使用方式粘招,如果你不在其中使用可以使用Vue.set的形式(保證Vue的存在)
你可以嘗試使用直接設置數(shù)組值(注釋部分的代碼),這時會發(fā)現(xiàn)頁面并不會改變偎球,使用Vue.set會讓Vue檢測到數(shù)組的變化洒扎,還可以使用數(shù)組的splice方法讓數(shù)組更新
this.listInfo.splice(0, 1, {id:1, value:'AA'});
如果這時你使用
this.listInfo.length = 2;
設置數(shù)組長度辑甜,視圖不會更新,解決方法一樣可以調(diào)用splice方法
this.listInfo.splice(2);
檢測對象的變化
- Vue不能檢測對象屬性的添加或刪除
事例如下:
<ul>
<li v-for="(value, key, $index) in tomInfo">{{$index}}. {{key | keyCheck}} : {{value}}</li>
</ul>
<button @click="addSchool">添加學校信息</button>
在methods方法中添加addSchool方法
methods: {
addSchool () {
this.tomInfo.school = '深圳大學';
console.log(this.tomInfo);
}
}
點擊頁面按鈕袍冷,我們在控制臺可以看到屬性是添加到指定數(shù)據(jù)上磷醋,但頁面視圖卻沒有重新渲染,解決方法同樣使用Vue.set方法
addSchool () {
this.$set(this.tomInfo, 'school', '深圳大學');
console.log(this.tomInfo);
}
這時視圖如期望變化胡诗,與數(shù)組的splice方法類似邓线,針對對象也可以使用Object.assign方法把更新后的對象重新賦值
addSchool () {
this.tomInfo = Object.assign({}, this.tomInfo, {school: '深圳大學'});
console.log(this.tomInfo);
}
使用Object.assign的好處就是可以同時添加多個屬性值
this.tomInfo = Object.assign({}, this.tomInfo, {school: '深圳大學', class: '軟件工程'});
一個需要特別注意的地方:v-for的優(yōu)先級比v-if的優(yōu)先級高
<li v-for="(value, key, $index) in tomInfo" v-if="$index > 1">{{$index}}. {{key | keyCheck}} : {{value}}</li>
因為v-for優(yōu)先級高于v-if,所以這個會先進行循環(huán)乃戈,然后再判斷是否符合條件進行展示
7) v-on
該指令是要來監(jiān)聽DOM事件褂痰,并在觸發(fā)時運行指定代碼(使用方法是v-on:事件名=“事件”)
<p @click="editInfo">{{info}}</p>
相關事件是放到methods下,@click是v-on:click的簡寫方式
methods: {
editInfo () {
this.info = 'info值被修改';
}
}
這時點擊頁面就會發(fā)現(xiàn)頁面數(shù)據(jù)發(fā)生改變症虑,事件可以接收參數(shù)來獲取原生DOM事件信息
editInfo (event) {
this.info = 'info值被修改';
console.log(event);
}
進行點擊,在控制臺會輸出原生DOM事件信息
<p @click="editInfo('修改info值')">{{info}}</p>
綁定事件時可以接收參數(shù)傳值
editInfo (msg) {
this.info = msg;
}
這時如果還要輸出DOM事件信息归薛,就要在傳參數(shù)時傳一個特殊參數(shù)$event
<p @click="editInfo('修改info值', $event)">{{info}}</p>
同一個元素可以綁定多個事件
<p @mouseover="mouseOver" @mouseout="mouseOut" @click="editInfo('修改info值', $event)">{{info}}</p>