vue常用指令v-model和v-for
1.v-model
一般用於表單input的雙向資料繫結
可以用 v-model
指令在表單 <input>
及 <textarea>
元素上建立雙向資料繫結。它會根據控制元件型別自動選取正確的方法來更新元素。儘管有些神奇,但 v-model
本質上不過是語法糖。它負責監聽使用者的輸入事件以更新資料,並對一些極端場景進行一些特殊處理。
v-model
會忽略所有表單元素的 value
、checked
、selected
特性的初始值而總是將 Vue 例項的資料作為資料來源。你應該通過 JavaScript 在元件的 data
選項中宣告初始值。
eg
<template> <div > <!--常用指令--> <!--1.v-model 一般用於表單input的雙向資料繫結--> <input type="text" v-model="msg"/> {{msg}} <br> <textarea v-model="msg0" placeholder="add multiple lines"></textarea> {{msg0}} <br> <div id='example-3'> <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> <br> <div id="example-4"> <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> <div id="example-5"> <select v-model="selected"> <option disabled value="">請選擇</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> </div> </template> <script> export default { name: 'HelloWorld', data () { return { msg: '常用指令input', msg0: '常用指令textarea', checkedNames:[], selected:'', picked: '' } } } </script> <style> </style>
效果:
2.v-for
2.1 v-for在數組裡面的用法
v-for 指令根據一組陣列的選項列表進行渲染。v-for 指令需要使用 item in items 形式的特殊語法,items 是源資料陣列並且 item 是陣列元素迭代的別名。eg:
2.1.1 v-for 在數組裡面用的時候支援一個可選引數index索引,與angular不同,它必須要在迴圈的時候給定一個引數index,才可以引用,即必須在(item,index)in items這樣引用後才可以得到index的值<template> <div class="hello"> <ul id="example-1"> <li v-for="item in items"> {{ item.message }} </li> </ul> </div> </template> <script> export default { name: 'HelloWorld', data () { return { items: [ { message: 'Foo' }, { message: 'Bar' }, { message: 'Bar' } ] } } } </script> <style > </style>
eg:
效果<template> <div class="hello"> <ul id="example-1"> <li v-for="(item,index) in items"> {{ item.message }}------{{index}} </li> </ul> </div> </template> <script> export default { name: 'HelloWorld', data () { return { items: [ { message: 'Foo' }, { message: 'Bar' }, { message: 'Bar' } ] } } } </script> <style > </style>
可以看見index並沒有顯示,
正確的使用方法
eg:
<template>
<div class="hello">
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}------{{index}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
items: [
{ message: 'Foo' },
{ message: 'Bar' },
{ message: 'Bar' }
]
}
}
}
</script>
<style >
</style>
效果:
2.2 v-for 在物件裡面的使用
在物件裡面使用如果沒有其他的可選屬性預設迴圈的是物件的值value
eg:
<template>
<div class="hello">
<ul id="example-1">
<li v-for="item in object">
{{ item }}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
}
}
</script>
<style >
</style>
效果:他顯示的就是物件的值
同樣的在物件裡面使用index也必須使用引數形成傳入才能取值到索引index,他還可以接受第三個引數,key鍵值,也是當做第三個引數傳入即可獲取使用
eg:
<template>
<div class="hello">
<ul id="example-1">
<li v-for="(item,index,key) in object">
{{ item }}------{{index}}_____{{key}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
}
}
</script>
<style >
</style>
效果:
需要注意的是接受的引數第一個必須是value,否在預設把第一個值當做value,也就是說如果引數只有index和key,最終會把第一個引數值當做value值,後面兩個引數的位置可以替換
以下摘自vue的api
key
當 Vue.js 用 v-for
正在更新已渲染過的元素列表時,它預設用“就地複用”策略。如果資料項的順序被改變,Vue 將不會移動 DOM 元素來匹配資料項的順序, 而是簡單複用此處每個元素,並且確保它在特定索引下顯示已被渲染過的每個元素。這個類似 Vue 1.x 的 track-by="$index"
。
這個預設的模式是高效的,但是隻適用於不依賴子元件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出。
為了給 Vue 一個提示,以便它能跟蹤每個節點的身份,從而重用和重新排序現有元素,你需要為每項提供一個唯一 key
屬性。理想的 key
值是每項都有的且唯一的 id。這個特殊的屬性相當於 Vue 1.x 的 track-by
,但它的工作方式類似於一個屬性,所以你需要用 v-bind
來繫結動態值 (在這裡使用簡寫):
<div v-for="item in items" :key="item.id"> <!-- 內容 --> </div> |
建議儘可能在使用 v-for
時提供 key
,除非遍歷輸出的 DOM 內容非常簡單,或者是刻意依賴預設行為以獲取效能上的提升。
因為它是 Vue 識別節點的一個通用機制,key
並不與 v-for
特別關聯,key 還具有其他用途,我們將在後面的指南中看到其他用途。
注意事項
由於 JavaScript 的限制,Vue 不能檢測以下變動的陣列:
- 當你利用索引直接設定一個項時,例如:
vm.items[indexOfItem] = newValue
- 當你修改陣列的長度時,例如:
vm.items.length = newLength
為了解決第一類問題,以下兩種方式都可以實現和 vm.items[indexOfItem] = newValue
相同的效果,同時也將觸發狀態更新:
// Vue.set Vue.set(example1.items, indexOfItem, newValue) |
// Array.prototype.splice example1.items.splice(indexOfItem, 1, newValue) |
為了解決第二類問題,你可以使用 splice
:
example1.items.splice(newLength) |
還是由於 JavaScript 的限制,Vue 不能檢測物件屬性的新增或刪除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 現在是響應式的 vm.b = 2 // `vm.b` 不是響應式的 |
對於已經建立的例項,Vue 不能動態新增根級別的響應式屬性。但是,可以使用 Vue.set(object, key, value)
方法向巢狀物件新增響應式屬性。例如,對於:
var vm = new Vue({ data: { userProfile: { name: 'Anika' } } }) |
你可以新增一個新的 age
屬性到巢狀的 userProfile
物件:
Vue.set(vm.userProfile, 'age', 27)
|
你還可以使用 vm.$set
例項方法,它只是全域性 Vue.set
的別名:
vm.$set(this.userProfile, 'age', 27)
|
有時你可能需要為已有物件賦予多個新屬性,比如使用 Object.assign()
或 _.extend()
。在這種情況下,你應該用兩個物件的屬性建立一個新的物件。所以,如果你想新增新的響應式屬性,不要像這樣:
Object.assign(this.userProfile, { age: 27, favoriteColor: 'Vue Green' }) |
你應該這樣做:
this.userProfile = Object.assign({}, this.userProfile, { age: 27, favoriteColor: 'Vue Green' }) |
有時,我們想要顯示一個數組的過濾或排序副本,而不實際改變或重置原始資料。在這種情況下,可以建立返回過濾或排序陣列的計算屬性。
例如:
<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
迴圈中) 你可以使用一個 method 方法:
<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 }) } } |
v-for
也可以取整數。在這種情況下,它將重複多次模板。
<div> <span v-for="n in 10">{{ n }} </span> </div> |
當它們處於同一節點,v-for
的優先順序比 v-if
更高,這意味著 v-if
將分別重複運行於每個 v-for
迴圈中。當你想為僅有的一些項渲染節點時,這種優先順序的機制會十分有用,如下:
<li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo }} </li> |
上面的程式碼只傳遞了未完成的 todos。
而如果你的目的是有條件地跳過迴圈的執行,那麼可以將 v-if
置於外層元素 (或 <template>
)上。如:
<ul v-if="todos.length"> <li v-for="todo in todos"> {{ todo }} </li> </ul> <p v-else>No todos left!</p> |
瞭解元件相關知識,檢視 元件。完全可以先跳過它,以後再回來檢視。
在自定義元件裡,你可以像任何普通元素一樣用 v-for
。
<my-component v-for="item in items" :key="item.id"></my-component>
|
2.2.0+ 的版本里,當在元件中使用
v-for
時,key
現在是必須的。
然而,任何資料都不會被自動傳遞到元件裡,因為元件有自己獨立的作用域。為了把迭代資料傳遞到元件裡,我們要用 props
:
<my-component v-for="(item, index) in items" v-bind:item="item" v-bind:index="index" v-bind:key="item.id" ></my-component> |
不自動將 item
注入到元件裡的原因是,這會使得元件與 v-for
的運作緊密耦合。明確元件資料的來源能夠使元件在其他場合重複使用。
下面是一個簡單的 todo list 的完整例子:
<div id="todo-list-example"> <input v-model="newTodoText" v-on:keyup.enter="addNewTodo" placeholder="Add a todo" > <ul> <li is="todo-item" v-for="(todo, index) in todos" v-bind:key="todo.id" v-bind:title="todo.title" v-on:remove="todos.splice(index, 1)" ></li> </ul> </div> |
注意這裡的 is="todo-item"
屬性。這種做法在使用 DOM 模板時是十分必要的,因為在 <ul>
元素內只有 <li>
元素會被看作有效內容。這樣做實現的效果與 <todo-item>
相同,但是可以避開一些潛在的瀏覽器解析錯誤。檢視 DOM 模板解析說明 來了解更多資訊。
Vue.component('todo-item', { template: '\ <li>\ {{ title }}\ <button v-on:click="$emit(\'remove\')">X</button>\ </li>\ ', props: ['title'] }) new Vue({ el: '#todo-list-example', data: { newTodoText: '', todos: [ { id: 1, title: 'Do the dishes', }, { id: 2, title: 'Take out the trash', }, { id: 3, title: 'Mow the lawn' } ], nextTodoId: 4 }, methods: { addNewTodo: function () { this.todos.push({ id: this.nextTodoId++, title: this.newTodoText }) this.newTodoText = '' } } }) |