Vue.js的指令
指令(Directives)是帶有 v-
字首的特殊屬性,指令屬性的值一般是單個JavaScript表示式(v-for除外)。指令的功能是,當表示式的值改變時,將其產生的連帶影響,響應式地作用於DOM。
常用的Vue指令有:
1、v-text 和 v-html
v-text
在標籤中顯示文字資料,資料物件中的資料會被原樣輸出,例如:
<span v-text="message"></span>
<!-- 簡寫方式 -->
<span>{{message}}</span>
複製程式碼
在模板中輸出真正的HTML,如果是使用 v-text
輸出帶標籤的字串的話,僅僅是想頁面中輸出帶標籤的HTML,但是不會對HTML程式碼進行解析,如果要解析HTML程式碼,就要使用 v-html
指令。例如:
<p v-text=“message”></p> <!-- 輸出帶有HTML標籤的文字內容 -->
<p v-html="message"></p> <!-- 輸出解析HTML程式碼後的內容 -->
<script type="text/javascript">
var app = new Vue({
el: '#app', //element
data: {
message: '<strong>Hello</strong> Vue!',
}
})
</script>
複製程式碼
上面程式碼執行後,輸出的結果為:
v-text
輸出的結果是:<strong>Hello</strong> Vue!
v-html
輸出的結果是:Hello Vue!
總結:
v-text
和 {{}}
表示式渲染資料,不解析標籤;
v-html
不僅可以渲染資料,而且可以解析標籤;
2、v-cloak
作用: v-clock
指令主要是解決對插值表示式 {{}}
的渲染前閃爍問題。
簡單來說,當網路比較慢時,網頁還在載入vue.js,這就會導致Vue來不及渲染,這是頁面就會顯示Vue原始碼。我們就可以使用 v-cloak
指令來解決這一問題。
演示:
HTML程式碼:
<div id="app">
{{context}}
</div>
複製程式碼
JS程式碼:
<script>
var app = new Vue({
el: '#app',
data: {
context:'網際網路頭部玩家鍾愛的健身專案'
}
});
</script>
複製程式碼
效果:
針對上面的這種情況,可以使用 v-cloak
指令解決閃爍問題。JS程式碼不變,只需要在div中新增 v-cloak
指令。使用 v-cloak
指令設定樣式,這些樣式會在Vue例項編譯結束時,從繫結的HTML元素上被移除。
程式碼示例:
HTML程式碼:
<div id="app" v-cloak>
{{context}}
</div>
複製程式碼
CSS程式碼:
[v-cloak]{
display: none;
}
複製程式碼
使用 v-cloak
指令之後的效果:
在簡單專案中,使用 v-cloak 指令是解決螢幕閃動的好方法。但在大型、工程化的專案中(webpack、vue-router)只有一個空的 div 元素,元素中的內容是通過路由掛載來實現的,這時我們就不需要用到 v-cloak 指令了。
3、v-bind 屬性繫結
v-bind
是用於繫結資料和元素屬性的,例如:
<div class="app">
<a v-bind:href="url">click me</a>
</div>
複製程式碼
var app = new Vue({
el:'.app',
data:{
url:"https://www.baidu.com",
}
});
複製程式碼
v-bind
後面是 屬性名=""
,可以理解為繫結了這個屬性,屬性的值去Vue例項的資料物件中獲取,當資料物件中對應的屬性值發生改變時,DOM中的屬性值也會隨著更新,可以在控制檯輸出測試。
同一個DOM元素上可以繫結多個屬性,例如:
<div class="app">
<a v-bind:href="url" v-bind:class="klass">click me</a>
<img v-bind:src="imgsrc">
</div>
複製程式碼
var app = new Vue({
el:'.app',
data:{
url:"https://www.baidu.com",
imgsrc:"https://cn.vuejs.org/images/logo.png",
class:"btn btn-default"
}
});
複製程式碼
v-bind
除了可以繫結一個簡單型別的資料之外,還可以繫結一個物件,例如:
<div class="app">
<a v-bind:class="{active:isActive}">click me</a>
</div>
複製程式碼
上面程式碼中,物件的名為 active
,表示要新增的類名, isActive
是vue中的資料,表示在什麼情況下新增該類名,即在Vue例項的資料物件中對應的值(isActive的值)為真是,才為DOM元素的class中新增 active
的樣式。
簡寫:
v-bind
指令可以簡化英文的冒號 :
,示例:
<div class="app">
<a v-bind:href="url">click me</a>
</div>
複製程式碼
可以簡化為:
<div class="app">
<a :href="url">click me</a>
</div>
複製程式碼
4、v-on 事件繫結
4.1、監聽事件
可以用 v-on
指令監聽 DOM 事件,並在觸發時執行一些 JavaScript 程式碼。 示例程式碼:
<div id="app">
<button v-on:click="counter += 1">Add 1</button>
<p>計算結果:{{ counter }}</p>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
counter: 0
}
})
複製程式碼
上面程式碼執行後,每次點選按鈕,資料物件中的 counter
屬性的值就會加1。
4.2、事件處理方法
v-on
是用於繫結事件的,例如,有一個按鈕,當點選該按鈕時執行一些操作:
<div id="app">
<button v-on:click="myclick">按鈕</button>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
},
methods: {
myclick:function() {
console.log('hello world')
}
}
複製程式碼
在 <button>
中 v-on:click
後面的值是一個方法,可以寫出 myclick()
,如果沒有引數的話,可以寫出 myclick
。該事件對應的方法不是定義在資料物件data中,而是定義在Vue例項的methods中。
4.3、內聯處理器中的方法
除了直接繫結到一個方法,也可以在內聯 JavaScript 語句中呼叫方法:
<div id="app">
<button v-on:click="say('hi')">Say hi</button>
<button v-on:click="say('what')">Say what</button>
</div>
複製程式碼
new Vue({
el: '#app',
methods: {
say: function (message) {
alert(message)
}
}
})
複製程式碼
上面程式碼執行後,當點選兩個按鈕時,都會執行 say()
方法。
有時也需要在內聯語句處理器中訪問原始的 DOM 事件。可以用特殊變數 $event
把它傳入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
複製程式碼
// ...
methods: {
warn: function (message, event) {
// 現在我們可以訪問原生事件物件
if (event) {
event.preventDefault()
}
alert(message)
}
}
複製程式碼
4.4、多事件處理方法
v-on
可以繫結多個事件,例如:
<div id="app">
<button v-on="{mouseenter:onenter,mouseleave:leave}">按鈕</button>
</div>
複製程式碼
或者是寫成:
<div id="app">
<button v-on:mouseenter="onenter" v-on:mouseleave="leave">按鈕</button>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
},
methods: {
onenter:function() {
console.log('onenter...')
},
leave:function() {
console.log('leave...')
}
}
})
複製程式碼
當繫結多個事件時,需要傳入一個物件,物件的鍵名就是事件名,物件的鍵值就是對應事件要執行的方法。
4.5、阻止表單預設提交
在使用form表單時,當點選提交按鈕,瀏覽器就會預設傳送一個get或者是post請求到指定頁面,重新整理整個頁面。有時為了增加表單驗證,需要阻止瀏覽器的預設行為,可以在繫結的提交方法中新增 $event
引數,$event
是Vue裡面的事件物件,Vue可以識別,程式碼示例:
<div class="app">
<form v-on:submit='onSubmit($event)'>
<input type="text" >
<button type="submit">提交</button>
</form>
</div>
複製程式碼
var app = new Vue({
el:'.app',
data:{
},
methods:{
onSubmit:function(e){
e.preventDefault(); //阻止瀏覽器的預設行為
console.log("onSubmited");
}
}
});
複製程式碼
其實,在Vue中已經封裝了阻止瀏覽器預設行為的修飾符,只需要在事件的後面加上 .prevent
修飾符,就可以組織預設事件,例如:
<div id="app">
<form v-on:submit.prevent="onSubmit($event)">
<input type="text">
<button type="submit">提交</button>
</form>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
},
methods: {
onSubmit: function() {
console.log('onsubmit....')
}
}
})
複製程式碼
4.6、v-on事件簡寫
v-on
可以簡寫為 @
符號,例如:
<div id="app">
<button v-on:click="myclick">按鈕</button>
</div>
複製程式碼
可以簡化為:
<div id="app">
<button @click="myclick">按鈕</button>
</div>
複製程式碼
4.7、事件修飾符
在事件處理程式中呼叫 event.preventDefault()
或 event.stopPropagation()
是非常常見的需求。儘管我們可以在方法中輕鬆實現這點,但更好的方式是:方法只有純粹的資料邏輯,而不是去處理 DOM 事件細節。
為了解決這個問題,Vue.js 為 v-on
提供了事件修飾符。之前提過,修飾符是由點開頭的指令字尾來表示的。
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止單擊事件繼續傳播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再過載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 新增事件監聽器時使用事件捕獲模式 -->
<!-- 即內部元素觸發的事件先在此處理,然後才交由內部元素進行處理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當在 event.target 是當前元素自身時觸發處理函式 -->
<!-- 即事件不是從內部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
<!-- 點選事件將只會觸發一次 -->
<a v-on:click.once="doThis"></a>
<!-- 滾動事件的預設行為 (即滾動行為) 將會立即觸發 -->
<!-- 而不會等待 `onScroll` 完成 -->
<!-- 這其中包含 `event.preventDefault()` 的情況 -->
<div v-on:scroll.passive="onScroll">...</div>
複製程式碼
4.8、按鍵修飾符
在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為 v-on
在監聽鍵盤事件時新增按鍵修飾符:
<!-- 只有在 `key` 是 `Enter` 時呼叫 `vm.submit()` -->
<input v-on:keyup.enter="submit">
複製程式碼
在Vue中已經廢除了 keyCode
的事件用法,但是可以使用 keyCode
屬性,例如:
<input v-on:keyup.13="submit">
複製程式碼
為了在必要的情況下支援舊瀏覽器,Vue 提供了絕大多數常用的按鍵碼的別名:
.enter
.tab
.delete
(捕獲“刪除”和“退格”鍵).esc
.space
.up
.down
.left
.right
有一些按鍵 (.esc
以及所有的方向鍵) 在 IE9 中有不同的 key
值, 如果你想支援 IE9,這些內建的別名應該是首選。
你還可以通過全域性 config.keyCodes
物件自定義按鍵修飾符別名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
複製程式碼
4.9、系統修飾符
可以用如下修飾符來實現僅在按下相應按鍵時才觸發滑鼠或鍵盤事件的監聽器。
.ctrl
.alt
.shift
.meta
例如:
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
複製程式碼
請注意修飾鍵與常規按鍵不同,在和 keyup
事件一起用時,事件觸發時修飾鍵必須處於按下狀態。換句話說,只有在按住 ctrl
的情況下釋放其它按鍵,才能觸發 keyup.ctrl
。而單單釋放 ctrl
也不會觸發事件。如果你想要這樣的行為,請為 ctrl
換用 keyCode
:keyup.17
。
.exact
修飾符
.exact
修飾符允許你控制由精確的系統修飾符組合觸發的事件。
<!-- 即使 Alt 或 Shift 被一同按下時也會觸發 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的時候才觸發 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 沒有任何系統修飾符被按下的時候才觸發 -->
<button @click.exact="onClick">A</button>
複製程式碼
滑鼠按鈕修飾符
.left
.right
.middle
這些修飾符會限制處理函式僅響應特定的滑鼠按鈕。
4.10、自定義按鍵修飾符別名
在Vue中可以通過config.keyCodes
自定義按鍵修飾符別名。例如,由於預先定義了keycode 116
(即F5
)的別名為f5
,因此在文字輸入框中按下F5
,會觸發prompt
方法,出現alert
。
<div id="app">
<input type="text" v-on:keydown.f5="prompt()" />
</div>
複製程式碼
Vue.config.keyCodes.f5 = 116;
var vm = new Vue({
el: '#app',
data: {
},
methods: {
prompt: function() {
alert("按下了F5!")
}
}
})
複製程式碼
5、v-if 和 v-show 條件渲染
5.1、v-if
v-if
指令用於條件性地渲染一塊內容,這塊內容只會在指令的表示式返回 true 時被渲染。例如:
<div id="app">
<div v-if="seen">可以被控制的內容</div>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
seen: true
}
})
複製程式碼
上面程式碼中,v-if
指令將根據表示式 seen 的值(true或false)來決定是否插入 div 元素。
可以使用 v-else-if
和 v-else
指令配合 v-if
一起使用,例如:
<div id="app">
<div v-if="score >= 90 && score <= 100">優秀</div>
<div v-else-if="score > 60 && score <=90">良好</div>
<div v-else>不及格</div>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
score: 90
}
})
複製程式碼
v-else
的元素必須緊跟在 v-if
或 v-else-if
的元素後面,而 v-else-if
的元素也必須緊跟在 v-if
元素的後面,v-else
和 v-else-if
都不能單獨使用。
由於 v-if
是一個指令,所以必須將它新增到一個元素上,但是如果想要切換多個元素,可以使用 <template>
元素當做不可見的包裹元素,並在該元素上使用 v-if
,最終渲染的結果不會包含 <template>
元素。例如:
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
複製程式碼
5.2、使用 key 管理可複用的元素
Vue會盡可能高效地渲染元素,通常會複用已有元素,而不是從頭開始渲染。這麼做除了使Vue變得非常快之外,還有一些其他好處。例如,如果專案中設計了兩種使用者登入的方式,可以使用 v-if
實現不同登入方式的切換。
<div id="app">
<template v-if="loginType">
<label>使用者名稱:</label>
<input placeholder="請輸入使用者名稱">
</template>
<template v-else>
<label>郵箱:</label>
<input placeholder="請輸入郵箱">
</template>
<button @click="toggleType">切換登入方式</button>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
loginType: true
},
methods: {
toggleType: function() {
this.loginType = !this.loginType;
}
}
})
複製程式碼
上面的程式碼中,切換 loginType
將不會清除使用者已經輸入的內容,因為兩個模板使用了相同的元素,<input>
元素被複用了,不會被替換掉,而是僅僅替換了元素中的 placeholder
屬性的值。效果如下:
這種情況肯定是不符合實際的需求的,所以Vue提供了一種方式來解決這個問題,即為不需要複用的元素上新增一個 key 屬性,告訴Vue這是兩個獨立的元素,不要複用它們。示例程式碼:
<div id="app">
<template v-if="loginType">
<label>使用者名稱:</label>
<input placeholder="請輸入使用者名稱" key="username-input">
</template>
<template v-else>
<label>郵箱:</label>
<input placeholder="請輸入郵箱" key="email-input">
</template>
<button @click="toggleType">切換登入方式</button>
</div>
複製程式碼
為 input
新增 key 屬性之後,每次切換時,輸入框都將被重新渲染,效果如下:
由於 <label>
元素沒有新增 key 屬性,所以仍然會被高效地複用。
5.3、v-show
Vue還提供了一種根據條件展示元素的選項,這就是 v-show
指令,示例:
<div id="app">
被控制的內容:<span v-show="ok">Hello</span>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
ok: false
}
})
複製程式碼
與 v-if
不同的是,v-show
的值無論是什麼,被該指令修飾的元素始終會被渲染並保留在DOM中,v-show
只是簡單地切換元素的CSS屬性 display:none
。上面程式碼在瀏覽器中的效果如下:
這裡需要注意的是,v-show
不支援 <template>
元素,也不支援 v-else
。
5.4、v-if 和 v-show 的區別
(1)顯隱過程:
雖然兩個指令都可以動態的顯示DOM元素,但是在執行上還是有很大區別的:
- v-if是動態的向DOM樹內新增或刪除DOM元素;
- v-show是通過設定DOM元素的display樣式屬性控制顯示或隱藏;
(2)編譯過程:
- v-if切換有一個區域性編譯/解除安裝的過程,切換過程中合適地銷燬和重建內部的事件監聽和子元件;
- v-show只是簡單的基於css切換;
(3)編譯條件:
- v-if是惰性的,如果初始條件為假,則什麼都不做;只有在條件第一次為真時才開始區域性編譯(當編譯被快取後,再次切換時會進行區域性解除安裝);
- v-show是在任何條件下(首次條件是否為真)都會被編譯,然後被快取,而且DOM元素保留;
(4)效能消耗:
- v-if有更高的切換效能消耗;
- v-show有更高的初始渲染效能消耗;
(5)使用場景:
- v-if適合執行時條件少改變的場景;
- v-show適合頻換切換的場景;
5.5、總結
v-if判斷是否載入,可以減輕伺服器的壓力,在需要時載入,但是會造成更高的切換開銷;
v-show調整DOM元素的CSS的display屬性,可以使客戶端操作更加流暢,但是有更高的初始渲染開銷;
v-if 注意事項
官方文件中不建議 v-if 和 v-for 一起使用,當它們一起使用時,v-for 具有比 v-if 更高的優先順序,這就意味著 v-if 將分別重複執行於每個 v-for 迴圈中。
6、v-for 列表渲染
6.1、遍歷陣列
可以使用 v-for
指令基於一個陣列來渲染列表。v-for
指令需要使用“元素 in 陣列
”形式的特殊語法,即 item in items
的語法形式,其中 items
是源資料的陣列,item
是被遍歷的陣列元素的別名。示例程式碼:
<ul id="app">
<li v-for="item in list">{{item}}</li>
</ul>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
list: [1,2,3,4,5]
}
})
複製程式碼
執行結果:
- 1
- 2
- 3
- 4
- 5
在 v-for
塊中,我們可以訪問所有父作用域的屬性。v-for
還支援一個可選的第二個引數,即當前項的索引。
<ul id="app">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
parentMessage: 'Parent',
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
複製程式碼
執行結果:
- Parent - 0 - Foo
- Parent - 1 - Bar
也可以用 of
替代 in
作為分隔符,因為它更接近 JavaScript 迭代器的語法:
<div v-for="item of items"></div>
複製程式碼
6.2、遍歷物件
可以用 v-for
來遍歷一個物件的屬性,示例程式碼:
<ul id="app">
<li v-for="value in object">
{{ value }}
</li>
</ul>
複製程式碼
new Vue({
el: '#app',
data: {
object: {
name: 'Tom',
age: 20,
sex: '男'
}
}
})
複製程式碼
結果:
- Tom
- 20
- 男
也可以提供第二個的引數為 property 名稱 (也就是鍵名):
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
複製程式碼
結果:
name:Tom
age:20
sex:男
複製程式碼
還可以用第三個引數作為索引:
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
複製程式碼
結果:
0. name:Tom
1. age:20
2. sex:男
複製程式碼
注意:使用v-for遍歷物件時,會按照 Object.keys()
的結果遍歷,但是不能保證它的結果在通過的JavaScript引擎下都一致。
6.3、遍歷整數
v-for
也可以接受整數。在這種情況下,它會把模板重複對應次數。
<div>
<span v-for="n in 10">{{ n }} </span>
</div>
複製程式碼
結果:
1 2 3 4 5 6 7 8 9 10
複製程式碼
6.4、在<template>
上使用v-for
類似於 v-if
,你也可以利用帶有 v-for
的 ` 來迴圈渲染一段包含多個元素的內容。比如:
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
複製程式碼
6.5、使用key屬性
當 Vue 正在更新使用 v-for
渲染的元素列表時,它預設使用“就地更新”的策略。如果資料項的順序被改變,Vue 將不會移動 DOM 元素來匹配資料項的順序,而是就地更新每個元素,並且確保它們在每個索引位置正確渲染。
為了給 Vue 一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,需要為每項提供一個唯一 key
屬性:
<div v-for="item in items" v-bind:key="item.id">
<!-- 內容 -->
</div>
複製程式碼
建議儘可能在使用 v-for
時提供 key
屬性,除非遍歷輸出的 DOM 內容非常簡單,或者是刻意依賴預設行為以獲取效能上的提升。
key屬性的注意事項:
- v-for迴圈時,key屬性只能使用number和string型別;
- key在使用時,必須使用v-bind屬性繫結的形式,指定key的值;
- 在元件中使用v-for迴圈時,必須在使用v-for的同時,指定唯一的key屬性值;
6.6、陣列的更新操作
Vue將被偵聽的陣列的變異方法(mutation method)進行了包裹,這裡的變異方法,是指陣列物件提供的呼叫後會改變陣列原始資料的方法。同時,也有非變異方法(non-mutation method),非變異方法不會改變原始陣列,而是返回一個新陣列。
Vue可以偵聽陣列的變異方法,所以陣列的變異方法被呼叫後也會觸發檢視的更新,這些方法包括:
push()
: 向陣列的末尾新增一個或更多元素,並返回新的長度;pop()
: 刪除陣列的最後一個元素並返回刪除的元素;shift()
: 刪除並返回陣列的第一個元素;unshift()
: 向陣列的開頭新增一個或更多元素,並返回新的長度;splice()
: 從陣列中新增或刪除元素;sort()
: 對陣列的元素進行排序;reverse()
: 反轉陣列的元素順序;
非變異方法不會更改原始陣列,總是返回一個新陣列,非變異方法包括:
filter()
: 檢測數值元素,並返回符合條件所有元素的陣列;concat()
: 連線兩個或更多的陣列, 該方法不會改變現有的陣列,而僅僅會返回被連線陣列的一個副本;slice()
: 選取陣列的的一部分,並返回一個新陣列;
所以當使用非變異方法時,可以用新陣列替換舊陣列:
vm.lsit = vm.list.filter(function(item){
return item.msg.match(/Foo/)
})
複製程式碼
上面程式碼中,將 filter()
方法返回的新陣列替換了Vue例項的資料物件中的陣列,雖然對Vue例項的資料物件重新賦值,但是並不會重新渲染整個列表,因為Vue為了使得DOM元素得到最大範圍的重用二實現了一些智慧的啟發式方法,所以用一個含有相同元素的陣列去替換原來的陣列是非常高效的操作。
但是,由於JavaScript的限制,Vue不能檢測以下陣列的變動:
- 使用索引直接設定陣列項時,例如:
vm.items[indexOfItem] = newValue
- 直接修改陣列的長度,例如:
vm.items.length = newLength
舉個例子:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是響應性的
vm.items.length = 2 // 不是響應性的
複製程式碼
解決第一類問題,即使用索引設定陣列項:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
//或者使用 vm.$set 例項方法,該方法是全域性方法Vue.set的一個別名
vm.$set(vm.items, indexOfItem, newValue)
複製程式碼
// 使用陣列的splice方法
vm.items.splice(indexOfItem, 1, newValue)
複製程式碼
解決第二類問題,即修改陣列length屬性,可以使用 splice 方法:
vm.items.splice(newLength)
複製程式碼
6.7、物件的更新操作
還是由於 JavaScript 的限制,Vue 不能檢測物件屬性的新增或刪除:
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` 現在是響應式的
vm.b = 2
// `vm.b` 不是響應式的
複製程式碼
對於已經建立的例項,Vue 不允許動態新增根級別的響應式屬性。但是,可以使用 Vue.set(object, propertyName, value)
方法向巢狀物件新增響應式屬性。例如,對於:
var vm = new Vue({
data: {
user: {
name: 'Anika'
}
}
})
複製程式碼
你可以新增一個新的 age
屬性到巢狀的 user
物件:
Vue.set(vm.user, 'age', 27)
複製程式碼
你還可以使用 vm.$set
例項方法,它只是全域性 Vue.set
的別名:
vm.$set(vm.user, 'age', 27)
複製程式碼
有時你可能需要為已有物件賦值多個新屬性,比如使用 Object.assign()
或 _.extend()
。在這種情況下,你應該用兩個物件的屬性建立一個新的物件。所以,如果你想新增新的響應式屬性, 應該這樣做:
vm.user = Object.assign({}, vm.user, {
age: 27,
favoriteColor: 'Vue Green'
})
複製程式碼
6.8、顯示過濾/排序後的結果
有時,我們想要顯示一個陣列經過過濾或排序後的版本,而不實際改變或重置原始資料。在這種情況下,可以建立一個計算屬性,來返回過濾或排序後的陣列。
例如:
<li v-for="n in evenNumbers">{{ n }}</li>
複製程式碼
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
複製程式碼
在計算屬性不適用的情況下 (例如,在巢狀 v-for
迴圈中) 你可以使用一個方法:
<li v-for="n in even(numbers)">{{ n }}</li>
複製程式碼
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
複製程式碼
7、v-model 表單資料繫結
7.1、基本用法
雙向資料繫結是Vue的核心特性之一,Vue的響應式原理是實現了資料—>檢視,而雙向資料繫結,就是在完成前面那一步之後,又做了檢視—>資料的操作。 v-model
指令可以在表單元素,例如:<input>
、<textarea>
以及 <select>
等元素上建立雙向資料繫結。它會根據控制元件型別自動選取正確的方法來更新元素。
v-model
會忽略所有表單元素的 value
、checked
、selected
屬性的初始值,以Vue例項的資料作為資料來源,可以通過Vue例項中的資料物件data中宣告表單的初始值。
文字
<div id="app">
<input v-model="msg" />
<p>結果:{{msg}}</p>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
msg: ''
}
})
複製程式碼
多行文字
<div id="app">
<textarea v-model="msg"></textarea>
<p>結果:{{msg}}</p>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
msg: ''
}
})
複製程式碼
在文字區域插值 ({{text}}
) 並不會生效,應用 v-model
來代替。
核取方塊
單個核取方塊繫結布林值:
<div id="app">
<input type="checkbox" v-model="checked" />
<label>{{ checked }}</label>
</div>
複製程式碼
var vm = new Vue({
el: '#app',
data: {
checked: false
}
})
複製程式碼
多個核取方塊,繫結到一個陣列:
<div id='app'>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
複製程式碼
new Vue({
el: '#app',
data: {
checkedNames: []
}
})
複製程式碼
單選按鈕
<div id="app">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
</div>
複製程式碼
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
複製程式碼
下拉框
單選時:
<div id="app">
<select v-model="selected">
<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
複製程式碼
new Vue({
el: '#app'
data: {
selected: ''
}
})
複製程式碼
多選時:
<div id="app">
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
複製程式碼
new Vue({
el: '#app',
data: {
selected: []
}
})
複製程式碼
用 v-for
渲染的動態選項:
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
複製程式碼
new Vue({
el: '#app',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
複製程式碼
7.2、值繫結
對於單選按鈕,核取方塊及選擇框的選項,v-model
繫結的值通常是靜態字串 (對於核取方塊也可以是布林值):
<!-- 當選中時,`picked` 為字串 "a" -->
<input type="radio" v-model="picked" value="a">
<!-- `toggle` 為 true 或 false -->
<input type="checkbox" v-model="toggle">
<!-- 當選中第一個選項時,`selected` 為字串 "abc" -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>
複製程式碼
但是有時我們可能想把值繫結到 Vue 例項的一個動態屬性上,這時可以用 v-bind
實現,並且這個屬性的值可以不是字串。
核取方塊
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
複製程式碼
// 當選中時
vm.toggle === 'yes'
// 當沒有選中時
vm.toggle === 'no'
複製程式碼
這裡的 true-value
和 false-value
attribute 並不會影響輸入控制元件的 value
attribute,因為瀏覽器在提交表單時並不會包含未被選中的核取方塊。如果要確保表單中這兩個值中的一個能夠被提交,(比如“yes”或“no”),請換用單選按鈕。
單選按鈕
<input type="radio" v-model="pick" v-bind:value="a">
複製程式碼
// 當選中時
vm.pick === vm.a
複製程式碼
下拉框的選項
<select v-model="selected">
<!-- 內聯物件字面量 -->
<option v-bind:value="{ number: 123 }">123</option>
</select>
複製程式碼
// 當選中時
typeof vm.selected // => 'object'
vm.selected.number // => 123
複製程式碼
7.3、修飾符
.lazy
在預設情況下,v-model
在每次 input
事件觸發後將輸入框的值與資料進行同步 (除了上述輸入法組合文字時)。你可以新增 lazy
修飾符,從而轉變為使用 change
事件進行同步:
<!-- 在“change”時而非“input”時更新 -->
<input v-model.lazy="msg" >
複製程式碼
.number
如果想自動將使用者的輸入值轉為數值型別,可以給 v-model
新增 number
修飾符:
<input v-model.number="age" type="number">
複製程式碼
這通常很有用,因為即使在 type="number"
時,HTML 輸入元素的值也總會返回字串。如果這個值無法被 parseFloat()
解析,則會返回原始的值。
.trim
如果要自動過濾使用者輸入的首尾空白字元,可以給 v-model
新增 trim
修飾符:
<input v-model.trim="msg">
複製程式碼