Vue.js — 列表渲染
阿新 • • 發佈:2021-01-20
1.列表渲染
1.1 v-for
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> </style> <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> </head> <body> <div id="app"> <ul> <li v-for="item in items" :key="item.id"> {{item.message}} </li> </ul> </div> <script> var vm = new Vue({ el: '#app', data: { items: [ {id: 1, message: 'Foo'}, {id: 2, message: 'Bar'} ] } }); </script> </body> </html>
我們可以用v-for
指令基於一個數組來渲染一個列表。item in items
的items
是源資料陣列,item
是被迭代的陣列元素的別名。
注意:一般情況下,我們會給<li>
指定key
,這裡的:key
表示資料繫結。
v-for
支援第二個引數,即當前項的索引。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> </style> <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> </head> <body> <div id="app"> <ul> <li v-for="(item, index) in items" :key="index"> {{item.message}} </li> </ul> </div> <script> var vm = new Vue({ el: '#app', data: { items: [ {id: 1, message: 'Foo'}, {id: 2, message: 'Bar'} ] } }); </script> </body> </html>
我們可以用v-for
指令遍歷一個物件的屬性。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> </style> <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> </head> <body> <div id="app"> <ul> <!-- <li v-for="value in object"> --> <!-- <li v-for="(value, name) in object"> --> <li v-for="(value, name, index) in object" :key="index"> {{value}} </li> </ul> </div> <script> var vm = new Vue({ el: '#app', data: { object: { title: 'How to do lists in Vue', author: 'Jane Doe', publishedAt: '2016-04-10' } } }); </script> </body> </html>
1.2 陣列更新檢測
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
</style>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in items" :key="index">
{{item.message}}
<button @click="updateItem(index, {message: 'Baz'})">更新</button>
<button @click="deleteItem(index)">刪除</button>
</li>
</ul>
<button @click="addItem({message: 'Boo'})">新增</button>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
items: [
{message: 'Foo'},
{message: 'Bar'}
]
},
methods: {
deleteItem: function(index){
this.items.splice(index, 1)
},
updateItem: function(index, newItem){
this.items.splice(index, 1, newItem)
},
addItem: function(newItem){
this.items.push(newItem)
}
}
});
</script>
</body>
</html>
注意:上面的splice
和push
方法不是陣列原生的方法,而是Vue為了偵聽陣列內部資料而重寫的方法。我們稱這些方法為變異方法(mutation method)。
變異方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
相比之下,非變異方法(non-mutating method)不會改變原始陣列,而是返回一個新陣列。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
</style>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="searchName">
<ul>
<li v-for="(item, index) in filteritems" :key="index">
{{item.message}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
searchName: '',
items: [
{message: 'Foo'},
{message: 'Bar'},
{message: 'Baz'},
{message: 'Boo'}
]
},
computed: {
filteritems: function(){
const {searchName, items} = this
let arr = [...items]
if(searchName.trim()){
// filter()為非變異方法
arr = items.filter(item => item.message.toLocaleLowerCase().indexOf(searchName.toLocaleLowerCase())!==-1)
}
return arr;
}
}
});
</script>
</body>
</html>
1.3 無法檢測的陣列變動
① 利用索引直接設定一個數組項,比如vm.items[indexOfItem] = newValue
。
② 修改陣列的長度,比如vm.items.length = newLength
。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
</style>
<!-- <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> -->
</head>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in items" :key="index">
{{item}}
</li>
</ul>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
items: ['a', 'b', 'c']
}
});
vm.items[1] = 'x'
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
</style>
<!-- <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> -->
</head>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in items" :key="index">
{{item}}
</li>
</ul>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
items: ['a', 'b', 'c']
}
});
Vue.set(vm.items, 1, 'x')
</script>
</body>
</html>
我們可以使用Vue.set(target, propertyName/index, value)
來實現響應式資料。
注意:物件變更檢測注意事項
1.4 在<template>
上使用v-for
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
</style>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<ul>
<template v-for="(item, index) in items" :key="index">
<li>{{item.name}}</li>
<li>----------</li>
</template>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
items: [
{name:'張飛'},
{name:'李四'},
]
}
});
</script>
</body>
</html>
我們可以使用帶有v-for
的<template>
來迴圈渲染一段包含多個元素的內容。
注意:我們不推薦在同一元素上使用v-if
和v-for
。當它們處於同一節點,v-for
的優先順序比v-if
更高。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
</style>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<ul v-if="todos.length">
<li v-for="todo in todos">
{{ todo }}
</li>
</ul>
<p v-else>No todos left!</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
todos: []
}
});
</script>
</body>
</html>
1.5 在元件上使用v-for
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
</style>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="todo-list-example">
<form v-on:submit.prevent="addNewTodo">
<label for="new-todo">Add a todo</label>
<input
v-model="newTodoText"
id="new-todo"
placeholder="E.g. Feed the cat"
>
<button>Add</button>
</form>
<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>
<script>
Vue.component('todo-item', {
template: '\
<li>\
{{ title }}\
<button v-on:click="$emit(\'remove\')">Remove</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 = ''
}
}
})
</script>
</body>
</html>
任何資料都不會被自動傳遞到元件裡,因為元件有自己獨立的作用域。
為了把迭代資料傳遞到元件裡,我們要使用prop。
注意:這裡is="todo-item"
實現的效果和<todo-item>
相同,但是可以避免一些潛在的瀏覽器解析錯誤。
參考: