一、列表初识
v-for指令:
- 用于展示列表数据
- 语法:
v-for="(item, index) in xxx" :key="yyy"
- 可遍历数组,对象,字符串,指定字数;其中遍历数组和对象最常用;
新建【列表渲染.html】
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>列表渲染</title>
<style>
</style>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<!--遍历数组-->
<h2>遍历数组</h2>
<ul>
<li v-for="person in persons" :key="person.id">
姓名:{{person.name}} - 年龄:{{person.age}}
</li>
</ul>
<hr>
<ul>
<li v-for="(person,index) in persons" :key="index">
姓名:{{person.name}} - 年龄:{{person.age}}
</li>
</ul>
<ul>
<li v-for="(person,index) of persons" :key="index">
姓名:{{person.name}} - 年龄:{{person.age}}
</li>
</ul>
<hr>
<hr>
<!--遍历对象-->
<h2>遍历对象</h2>
<ul>
<li v-for="(value,key) of car" :key="key" >
{{key}} - {{value}}
</li>
</ul>
<!--遍历字符串-->
<h2>遍历字符串</h2>
<ul>
<li v-for="(str,index) of hello" :key="index" >
索引值:{{index}} - 字符串值:{{str}}
</li>
</ul>
<!--遍历指定次数-->
<h2>遍历指定次数</h2>
<ul>
<li v-for="(num,index) of 5" :key="index" >
索引值:{{index}} - 数值{{num}}
</li>
</ul>
</div>
<!--阻止vue在启动时生成生产提示 -->
<script type="text/javascript">
Vue.config.productionTip=false
// 创建Vue实例
new Vue({
el:"#root",
data:{
persons:[
{
id: "001",
name:"张三",
age: 28,
},
{
id: "002",
name:"王五",
age: 18,
},
{
id: "003",
name:"李四",
age: 38,
}
],
car:{
name:"奥迪A8",
price:"70W"
},
hello: "hello",
},
methods:{
}
})
</script>
</body>
</html>
key的作用和原理
1. 使用index作为key
新建文件【使用index作为key.html】
关注点:使用index作为key
注意:如果不写key,vue会默认使用index作为key。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>key的原理</title>
<style>
</style>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<!--遍历数组-->
<h2>遍历数组</h2>
<button @click="add">添加一个人</button>
<ul>
<li v-for="(person,index) of persons" :key="index">
姓名:{{person.name}} - 年龄:{{person.age}}
<input type="text">
</li>
</ul>
</div>
<!--阻止vue在启动时生成生产提示 -->
<script type="text/javascript">
Vue.config.productionTip=false
// 创建Vue实例
new Vue({
el:"#root",
data:{
persons:[
{
id: "001",
name:"张三",
age: 28,
},
{
id: "002",
name:"王五",
age: 18,
},
{
id: "003",
name:"李四",
age: 38,
}
],
},
methods:{
add(){
const p = {"id": "004", "name": "jane", "age":30}
this.persons.unshift(p)
}
}
})
</script>
</body>
</html>
使用浏览器打开,每一个输入框都输入值后,点击按钮添加一个人,效果如下:
具体作用原理可看下图:
2. 使用id作为key
新建文件【使用id作为key.html】
关注点:使用id作为key
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>key的原理</title>
<style>
</style>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<!--遍历数组-->
<h2>遍历数组</h2>
<button @click="add">添加一个人</button>
<ul>
<li v-for="(person,index) of persons" :key="person.id">
姓名:{{person.name}} - 年龄:{{person.age}}
<input type="text">
</li>
</ul>
</div>
<!--阻止vue在启动时生成生产提示 -->
<script type="text/javascript">
Vue.config.productionTip=false
// 创建Vue实例
new Vue({
el:"#root",
data:{
persons:[
{
id: "001",
name:"张三",
age: 28,
},
{
id: "002",
name:"王五",
age: 18,
},
{
id: "003",
name:"李四",
age: 38,
}
],
},
methods:{
add(){
const p = {"id": "004", "name": "jane", "age":30}
this.persons.unshift(p)
}
}
})
</script>
</body>
</html>
使用浏览器打开,每一个输入框都输入值后,点击按钮添加一个人,效果如下:
具体作用原理可看下图:
3. 总结
-
虚拟DOM中key的作用
- key是虚拟DOM对象得标识,当数据发生变化时,vue会根据【新数据】生成【新的虚拟DOM】。
- 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下。
-
比较规则
- 旧的DOM中找到了与新虚拟DOM相同的key
- 若虚拟DOM中内容没变,直接使用之前的真实DOM!
- 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
- 旧虚拟DOM未找到与新虚拟DOM相同key
- 创建新的展示DOM,随后渲染到页面。
- 旧的DOM中找到了与新虚拟DOM相同的key
-
用index作为key可能会引发的问题
- 若对数进行:逆向添加,逆向删除等破坏顺序操作会产生没有必要的真实DOM更新==>页面效果没有问题,但是效率低。
- 如果结构中还包含输入类的DOM会产生错误的DOM更新==>界面有问题。
-
开发中如何选择key
- 最好使用每条数据的为之一标识作为key,比如id,手机号,身份证号,学号等唯一值。
- 如果不存在对数据的逆向添加,逆向删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
二、列表过滤
新建【列表过滤.html】
需求:可以使用搜索关键字对人员列表的姓名进行模糊搜索
注意:当watch和computed都可以实现时,推荐使用computed。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>列表过滤</title>
<style>
</style>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字进行搜索" v-model="keyWord">
<ul>
<li v-for="person in filPersons" :key="person.id">
姓名:{{person.name}} - 年龄:{{person.age}}
</li>
</ul>
</div>
<!--阻止vue在启动时生成生产提示 -->
<script type="text/javascript">
Vue.config.productionTip=false
// 创建Vue实例--watch实现
// new Vue({
// el:"#root",
// data:{
// keyWord:"",
// persons:[
// {
// id: "001",name:"马冬梅",age: 28,gender: "female"
// },
// {
// id: "002", name:"周杰伦",age: 18,gender: "male"
// },
// {
// id: "003",name:"温兆伦",age: 38,gender: "male"
// },
// {
// id: "004",name:"周冬雨",age: 38,gender: "female"
// }
// ],
// filPersons: []
// },
// watch:{
// // keyWord(val){
// // this.filPersons = this.persons.filter((person)=>{
// // return persons.indexOf(val) != -1
// // })
// // }
// keyWord:{
// immediate:true,
// handler(val){
// this.filPersons = this.persons.filter((person)=>{
// return person.name.indexOf(val) != -1
// })
// }
// }
// }
// })
// 创建Vue实例--computed实现
new Vue({
el:"#root",
data:{
keyWord:"",
persons:[
{
id: "001",name:"马冬梅",age: 28,gender: "female"
},
{
id: "002", name:"周杰伦",age: 18,gender: "male"
},
{
id: "003",name:"温兆伦",age: 38,gender: "male"
},
{
id: "004",name:"周冬雨",age: 38,gender: "female"
}
],
},
computed:{
filPersons(){
return this.persons.filter((person)=>{
return person.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
</body>
</html>
三、列表排序
新建【列表排序.html】
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>列表排序</title>
<style>
</style>
<!-- 引入Vue -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字进行搜索" v-model="keyWord"><br>
<br>
<button @click="sortType=2">年龄升序</button>
<button @click="sortType=1">年龄降序</button>
<button @click="sortType=0">原顺序</button>
<ul>
<li v-for="person in filPersons" :key="person.id">
姓名:{{person.name}} - 年龄:{{person.age}}
</li>
</ul>
</div>
<!--阻止vue在启动时生成生产提示 -->
<script type="text/javascript">
Vue.config.productionTip=false
// 创建Vue实例--computed实现
new Vue({
el:"#root",
data:{
keyWord:"",
sortType: 0, // 0原顺序,1 降序 2升序
persons:[
{
id: "001",name:"马冬梅",age: 28,gender: "female"
},
{
id: "002", name:"周杰伦",age: 18,gender: "male"
},
{
id: "003",name:"温兆伦",age: 38,gender: "male"
},
{
id: "004",name:"周冬雨",age: 8,gender: "female"
}
],
},
computed:{
filPersons(){
const arr = this.persons.filter((person)=>{
return person.name.indexOf(this.keyWord) !== -1
})
// 判断一下是否需要排序
if(this.sortType){
arr.sort((person1, person2)=>{
// 函数体
return this.sortType === 1 ? person2.age - person1.age : person1.age -person2.age
})
}
return arr
}
}
})
</script>
</body>
</html>