vue概述sd
在官方文檔中,有一句話對Vue的定位說的很明確:
Vue.js 的核心是一個允許采用簡潔的模板語法來聲明式地將數(shù)據(jù)渲染進 DOM 的系統(tǒng)
Vue在我的理解下,其實很像mvvm架構(gòu)中,對vm的實行。在mvvm架構(gòu)中,viewModel是負(fù)責(zé)把view和model關(guān)聯(lián)起來,把model的數(shù)據(jù)同步到view顯示出來,把view的修改同步回model。在Vue的data屬性中可設(shè)定相關(guān)變量,并把這些變量和Dom進行關(guān)聯(lián),達到修改data中屬性即可修改Dom的功能 ( model(data) --> Vue --> view(dom) )。在Dom上,通過觸發(fā)綁定方法,對相關(guān)數(shù)據(jù)進行修改 ( view(dom) --> Vue --> model(data) )。按這個思路來理解Vue,可以大概猜想出Vue有些功能為什么要被設(shè)計出來。
- 插值:快速實現(xiàn)data和view的快速綁定,
- 指令:對插值的補充,作用于模板上,用來實現(xiàn)模板的重復(fù)生成(v-for),動態(tài)顯示(v-show, v-if),屬性綁定(v-bind),事件綁定(v-on),對表單的增強(v-model)
- 計算屬性和觀察屬性:對插值和指令的補充,動態(tài)響應(yīng)更新數(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的值,對應(yīng)DOM(p標(biāo)簽)的就會發(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>
如果這里是設(shè)置常用的class,id,title屬性是沒什么問題,但如果是自定義屬性比如data-cusData這種類型的數(shù)據(jù),就會被強制轉(zhuǎn)為data-cusdata
如果要綁定多個屬性值可以使用對象的形式
<p v-bind='{id: elemId, class: elemClass, "data-cusData": cusData}'>{{info}}</p>
Data中設(shè)置修改如下
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的簡寫
對應(yīng)data修改如下:
{
...
redFlag: true,
fontFlag: false
}
頁面渲染結(jié)果如下:
<p class="static red">Hello vue!</p>
如例子顯示,綁定對象的形式可以動態(tài)切換多個class,同時也支持與普通class共存
當(dāng)綁定對象要進行多個class值的設(shè)定,沿用上面的寫法會顯得繁瑣,我們可以把綁定的對象換成一個計算屬性,在計算屬性中動態(tài)的設(shè)定返回值。
<p class='static' :class='classObj'>{{info}}</p>
在計算屬性中設(shè)定相關(guān)值
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設(shè)為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")
當(dāng)使用對象語法進行多個css屬性設(shè)置時,可以使用計算屬性進行綁定
<p :style='styleObj'>{{info}}</p>
計算屬性設(shè)置如下
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è)定樣式的方式如果只是綁定單個對象是沒問題的,但如果要使用數(shù)組的形式綁定多個對象就無法生效(解決方法參看下面)。
4) :style綁定數(shù)組語法
使用:class綁定數(shù)組使用方法見下例:
<p :style='[colorStyle, fontStyle, backgroundColor]'>{{info}}</p>
這個時候要保證對應(yīng)數(shù)組對象是對象的形式(上例是字符串形式):
這個例子中綁定對象的值分別在data和計算屬性中設(shè)定,只是做演示,表示這個綁定值,可以是不同的來源值進行混合
在data中設(shè)定colorStyle
{
...
colorStyle: {
color: 'red'
}
...
}
在計算屬性中設(shè)定fontStyle和backgroundColor
computed: {
fontStyle () {
return {fontSize: this.fontSize}
},
backgroundColor () {
return {backgroundColor: this.bgColor}
}
}
這時的渲染結(jié)果和上例是一致的,但如果你把其中一個值,改成字符串形式
fontStyle () {
return `fontSize: ${this.fontSize};`
}
這時你會發(fā)現(xiàn)Vue會忽略當(dāng)前值的設(shè)定,所以在使用:style形式時,最好按對象形式返還設(shè)定的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中設(shè)定一個infoObj
{
...
infoObj: {
msg: 'Hello vue!'
}
...
}
這時頁面渲染為
<p>{
"msg": "Hello vue!"
}</p>
如果你進行下面的設(shè)定
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ù)通過計算屬性進行返回(上例只是個樣式,正常情況下計算屬性會包含相關(guān)邏輯處理,相關(guān)會在計算屬性那部分講解,這里就不展開了)
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>
如例中假設(shè),比如我現(xiàn)在有個接口返回用戶是否登陸,拿到接口返回數(shù)據(jù),我們就可以根據(jù)接口返回的相關(guān)字段,動態(tài)的設(shè)定某一處的class。
通過修飾符.prop綁定DOM屬性
如果在綁定屬性后使用.prop修飾符,會忽略其他對該值的設(shè)定,強制使用設(shè)定的屬性值
<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>
對應(yīng)的綁定值就會變成一個普通的屬性值
<p class="pId" text-content="Hello vue!">測試數(shù)據(jù)</p>
2) v-html
該指令是用來直接輸出HTML內(nèi)容
<div v-html="html"></div>
在data中設(shè)定如下值
{
...
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中設(shè)定showFlag的值
{
...
showFlag: true,
...
}
這時頁面渲染為
<p>Hello vue!</p>
如果showFlag設(shè)為false,頁面渲染為
<p style="display: none;">Hello vue!</p>
v-show指令使用時有如下內(nèi)容需要注意:
- v-show不支持<template>元素,因為template標(biāo)簽的元素的內(nèi)容不會被渲染,所以對該標(biāo)簽使用v-show去改變其的display屬性是沒有意義的。
- v-show不支持和v-else一起使用,v-show只管當(dāng)前元素的顯示與否
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中設(shè)定type一個隨意的值
{
...
type: 'E',
...
}
這時頁面渲染為
<p>D</p>
由于v-if會對元素進行重建或者銷毀,而Vue在渲染時會盡可能復(fù)用已有元素,針對普通元素這個指令使用起來是沒問題的,但針對一些表單元素就有問題了。
<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中添加相關(guān)方法
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標(biāo)簽。
如果認(rèn)為這是一個問題,可以使用Vue提供的防重的方式,使用key添加一個唯一的關(guān)鍵值。做以下改造
<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下設(shè)定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>
從這個例子,我們可以看出該指令是在當(dāng)前元素進行循環(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中添加相關(guān)數(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ù)通常是按照J(rèn)SON格式給出,key值都是英文,這時前端就要對key值進行一個轉(zhuǎn)為中文的操作,我們現(xiàn)在要對已經(jīng)處理過的數(shù)據(jù)在進行簡單處理(邏輯并不復(fù)雜),這時我們就需要使用過濾器(本部分只簡單介紹)
在filters(這是組件內(nèi)的寫法)下添加相關(guān)過濾器
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>
關(guān)于v-for使用:key提升性能的解釋
在Vue的官方文檔中介紹v-for指令時,提到使用key值提升渲染性能,具體原因官方?jīng)]有詳細介紹,只說Vue在進行渲染時進行的是“就地復(fù)用”策略。如果數(shù)據(jù)項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據(jù)項的順序, 而是簡單復(fù)用此處每個元素,并且確保它在特定索引下顯示已被渲染過的每個元素。
參考如下實例,有助于理解這段話:
<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>
渲染的信息如我們所預(yù)期的一致,但是我們剛剛輸入的文字輸入框卻沒有按預(yù)期的下移,比較明顯的被直接復(fù)用,這也就是官方文檔中提到的如果數(shù)據(jù)項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據(jù)項的順序,不過在這個例子中這種Vue的默認(rèn)處理方式是不符合我們的預(yù)期,所以這時要使用key值來標(biāo)記每個節(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就會按預(yù)期的排序
在這里會有個容易忽略的問題,如果你把key的綁定值換成數(shù)組序號的$index值
:key="$index"
Vue會忽略這個key的設(shè)定,還是按照未設(shè)定key時的方式進行渲染,原因(以下是個人理解,可能根本原因并不是這樣)是此時key值綁定的是數(shù)組的序號值(數(shù)字是不可變值),雖然可以通過addList方法觸發(fā)listInfo值的更新,但是無法觸發(fā)key綁定值的更新,Vue會把新加的數(shù)據(jù)當(dāng)作普通數(shù)據(jù),采取"就地復(fù)用"的策略(也就是官方文檔中提到的確保它在特定索引下顯示已被渲染過的每個元素),直接更新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中設(shè)定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);
}
這時如果進行相關(guān)操作,就會發(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è)置數(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è)置數(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è)置數(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">添加學(xué)校信息</button>
在methods方法中添加addSchool方法
methods: {
addSchool () {
this.tomInfo.school = '深圳大學(xué)';
console.log(this.tomInfo);
}
}
點擊頁面按鈕,我們在控制臺可以看到屬性是添加到指定數(shù)據(jù)上,但頁面視圖卻沒有重新渲染,解決方法同樣使用Vue.set方法
addSchool () {
this.$set(this.tomInfo, 'school', '深圳大學(xué)');
console.log(this.tomInfo);
}
這時視圖如期望變化,與數(shù)組的splice方法類似,針對對象也可以使用Object.assign方法把更新后的對象重新賦值
addSchool () {
this.tomInfo = Object.assign({}, this.tomInfo, {school: '深圳大學(xué)'});
console.log(this.tomInfo);
}
使用Object.assign的好處就是可以同時添加多個屬性值
this.tomInfo = Object.assign({}, this.tomInfo, {school: '深圳大學(xué)', 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>
相關(guān)事件是放到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>