v-for
指令:
- 用于展示列表数据
- 语法:
<li v-for="(item, index) in xxx" :key="yyy">
,其中key可以是index,也可以是遍历对象的唯一标识 - 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 遍历列表-->
<h2>人员列表</h2>
<ul>
<li v-for="p in persons" :key="p.id">{{p.name}} - {{p.age}}</li>
</ul>
<!-- <h2>人员列表</h2>-->
<!-- <ul>-->
<!-- <li v-for="(p,index) in persons" :key="index">{{p.name}} - {{p.age}}</li>-->
<!-- </ul>-->
<!-- <h2>人员列表</h2>-->
<!-- <ul>-->
<!-- <li v-for="(a,b,c) in persons">{{a}} - {{b}} -- {{c}}</li>-->
<!-- </ul>-->
<!-- 遍历对象-->
<h2>汽车信息</h2>
<ul>
<li v-for="(value,k) in cars" :key="k">{{k}} -- {{value}}</li>
</ul>
<!-- 遍历字符串-->
<h3>测试遍历字符串</h3>
<ul>
<li v-for="(char,index) in strs" :key="index">
{{char}} -- {{index}}
</li>
</ul>
<!-- 遍历指定次数-->
<h2>测试遍历指定次数</h2>
<ul>
<li v-for="(number,index) in 5">{{number}} -- {{index}}</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: "#app",
data: {
persons: [
{id: '001', name: '张三', age: 18},
{id: '002', name: '李四', age: 19},
{id: '003', name: '王五', age: 20}
],
cars: {
name: 'aodi',
price: '18',
color: 'balck'
},
strs: 'hello'
}
})
</script>
</body>
</html>
key作用与原理
react、vue中的key有什么作用?(key的内部原理)
虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
对比规则:
旧虚拟DOM中找到了与新虚拟DOM相同的key:
若虚拟DOM中内容没变, 直接使用之前的真实DOM
若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到到页面
用index作为key可能会引发的问题:
若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
开发中如何选择key?
最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>人员列表</h2>
<button @click.once="add">添加老刘</button>
<ul>
<h3>index作为key</h3>
<!-- index作为key-->
<li v-for="(p,index) in persons" :key="index">
{{p.name}} - {{p.age}}<input type="text">
</li>
</ul>
<ul>
<!-- p.id作为key-->
<h3>p.id作为key</h3>
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}} - {{p.age}}<input type="text">
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: "#app",
data: {
persons: [
{id: '001', name: '张三', age: 18},
{id: '002', name: '李四', age: 19},
{id: '003', name: '王五', age: 20}
]
},
methods: {
add() {
const p = {id: '004', name: '老刘', age: 40}
this.persons.unshift(p)
}
}
})
</script>
</body>
</html>
列表过滤
方法一:使用监听属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>人员列表</h2>
<input type="text" placeholder="请输入姓名" v-model="keyWord">
<ul>
<li v-for="(p,index) in filpersons" :key="p.id">
{{p.name}} - {{p.age}} - {{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: "#app",
data: {
keyWord: "",
persons: [
{id: '001', name: '马冬梅', age: 19, sex: '女'},
{id: '002', name: '周冬雨', age: 20, sex: '女'},
{id: '003', name: '周杰伦', age: 21, sex: '男'},
{id: '004', name: '温兆伦', age: 22, sex: '男'}
],
filpersons: []
},
watch: {
keyWord: {
immediate: true,
handler(newval) {
this.filpersons = this.persons.filter((p) => {
return p.name.indexOf(newval) !== -1
})
}
}
}
})
</script>
</body>
</html>
方法二:使用计算属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>人员列表</h2>
<input type="text" placeholder="请输入姓名" v-model="keyWord">
<ul>
<li v-for="(p,index) in filpersons" :key="p.id">
{{p.name}} - {{p.age}} - {{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: "#app",
data: {
keyWord: "",
persons: [
{id: '001', name: '马冬梅', age: 19, sex: '女'},
{id: '002', name: '周冬雨', age: 20, sex: '女'},
{id: '003', name: '周杰伦', age: 21, sex: '男'},
{id: '004', name: '温兆伦', age: 22, sex: '男'}
],
},
computed: {
filpersons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
</body>
</html>
列表排序
先过滤在排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<h2>人员列表</h2>
<input type="text" placeholder="请输入姓名" v-model="keyWord">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="(p,index) in filpersons" :key="p.id">
{{p.name}} - {{p.age}} - {{p.sex}}
</li>
</ul>
</div>
<script>
Vue.config.productionTip = false
const vm = new Vue({
el: "#app",
data: {
keyWord: "",
sortType: 0,// 0原顺序 1降序 2升序
persons: [
{id: '001', name: '马冬梅', age: 19, sex: '女'},
{id: '002', name: '周冬雨', age: 20, sex: '女'},
{id: '003', name: '周杰伦', age: 21, sex: '男'},
{id: '004', name: '温兆伦', age: 22, sex: '男'}
],
},
computed: {
filpersons() {
const arr = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
if (this.sortType) {
arr.sort((a, b) => {
return this.sortType === 1 ? b.age - a.age : a.age - b.age
})
}
return arr
}
}
})
</script>
</body>
</html>