12_列表渲染
1.基本列表
总结:
v-for指令:
1.用于展示列表数据
2.语法:v-for=("item,index") in xxx" :key="yyy"
3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
- 遍历数组
- 遍历对象
- 遍历字符串
- 遍历指定次数
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>基本列表</title> 8 <script type="text/javascript" src="../js/vue.js"></script> 9 </head> 10 <body> 11 <div id="root"> 12 <h2>人员列表</h2> 13 <ul> 14 <!-- 遍历数组 --> 15 <li v-for="p in personArr" :key="p.id"> 16 {{p.name}}-{{p.age}} 17 </li> 18 </ul> 19 <!-- 遍历对象 --> 20 <h2>汽车信息</h2> 21 <ul> 22 <li v-for="(value,k) of car" :key="key"> 23 {{k}}-{{value}} 24 </li> 25 </ul> 26 <!-- 遍历字符串 --> 27 <h2>测试遍历字符串</h2> 28 <ul> 29 <li v-for="(char,index) of str" :key="key"> 30 {{char}}-{{key}} 31 </li> 32 </ul> 33 <!-- 遍历指定次数 --> 34 <h2>测试指定次数</h2> 35 <ul> 36 <li v-for="(number,index) of 5" :key="key"> 37 {{number}}-{{index}} 38 </li> 39 </ul> 40 </div> 41 </body> 42 <script type="text/javascript"> 43 Vue.config.productionTips = false //阻止vue在启动时生成生产提示 44 new Vue({ 45 el:'#root', 46 data:{ 47 personArr:[ 48 {id:'001',name:'张三',age:18}, 49 {id:'002',name:'李四',age:19}, 50 {id:'003',name:'王五',age:20}, 51 ], 52 car:{ 53 name:'宝马', 54 price:'30万', 55 color:'蓝色' 56 }, 57 str:'hello' 58 } 59 }) 60 </script> 61 </html>
2.key的作用和原理
总结:
1.虚拟DOM中的key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成新的【虚拟DOM】,
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
.若虚拟DOM中内容没变,直接使用之前的真实DOM !
.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:
1.若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新==〉界面效果没问题,但效率低。
2.如果结构中还包含输入类的DOM:
会产生错误DOM更新==>界面有问题。
4.开发中如何选择key? :
1.最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>key的原理</title> 8 <script type="text/javascript" src="../js/vue.js"></script> 9 </head> 10 <body> 11 <div id="root"> 12 <h2>人员列表</h2> 13 <ul> 14 <!-- 遍历数组 --> 15 <button @click.once="add">添加一个老刘</button> 16 <li v-for="(p,index) in personArr" :key="p.id"> 17 {{p.name}}-{{p.age}} 18 <input type="text"> 19 </li> 20 </ul> 21 </div> 22 </body> 23 <script type="text/javascript"> 24 Vue.config.productionTips = false //阻止vue在启动时生成生产提示 25 new Vue({ 26 el:'#root', 27 data:{ 28 personArr:[ 29 {id:'001',name:'张三',age:18}, 30 {id:'002',name:'李四',age:19}, 31 {id:'003',name:'王五',age:20}, 32 ] 33 }, 34 methods: { 35 add(){ 36 const p = {id:'004',name:'老刘',age:40} 37 this.personArr.unshift(p) 38 } 39 }, 40 }) 41 </script> 42 </html>
3.列表过滤
先收集用户的输入
再过滤信息
- 用watch实现
- 用conputed实现
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>列表过滤</title> 8 <script type="text/javascript" src="../js/vue.js"></script> 9 </head> 10 <body> 11 <div id="root"> 12 <h2>人员列表</h2> 13 <input type="text" placeholder="请输入名字" v-model="keyword"> 14 <ul> 15 <li v-for="p in filpersons" :key="p.id"> 16 {{p.name}}-{{p.age}} 17 </li> 18 </ul> 19 </div> 20 </body> 21 <script type="text/javascript"> 22 Vue.config.productionTips = false //阻止vue在启动时生成生产提示 23 //用watch实现 24 //#region 25 /* new Vue({ 26 el:'#root', 27 data:{ 28 keyword:'', 29 personArr:[ 30 {id:'001',name:'马冬梅',age:18,sex:'女'}, 31 {id:'002',name:'张冬梅',age:19,sex:'女'}, 32 {id:'003',name:'周杰伦',age:20,sex:'男'}, 33 {id:'004',name:'谢柏伦',age:21,sex:'男'}, 34 ], 35 }, 36 filpersons:[], 37 watch:{ 38 keyword:{ 39 immediate:true, 40 handler(value){ 41 this.filpersons = this.personArr.filter((p) =>{ 42 return p.name.indexOf(value) !== -1 43 }) 44 } 45 } 46 } 47 }) */ 48 //#endregion 49 //用conputed实现 50 new Vue({ 51 el:'#root', 52 data:{ 53 keyword:'', 54 personArr:[ 55 {id:'001',name:'马冬梅',age:18,sex:'女'}, 56 {id:'002',name:'张冬梅',age:19,sex:'女'}, 57 {id:'003',name:'周杰伦',age:20,sex:'男'}, 58 {id:'004',name:'谢柏伦',age:21,sex:'男'}, 59 ] 60 }, 61 computed:{ 62 filpersons(){ 63 return this.filpersons = this.personArr.filter((p) =>{ 64 return p.name.indexOf(this.keyword) !== -1 65 }) 66 67 } 68 } 69 }) 70 71 </script> 72 </html>
4.列表排序
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>列表排序</title> 8 <script type="text/javascript" src="../js/vue.js"></script> 9 </head> 10 <body> 11 <div id="root"> 12 <h2>人员列表</h2> 13 <input type="text" placeholder="请输入名字" v-model="keyword"> 14 <button @click="sortType = 2">年龄升序</button> 15 <button @click="sortType = 1">年龄降序</button> 16 <button @click="sortType = 0">年龄原序</button> 17 <ul> 18 <li v-for="p in filpersons" :key="p.id"> 19 {{p.name}}-{{p.age}} 20 </li> 21 </ul> 22 </div> 23 </body> 24 <script type="text/javascript"> 25 Vue.config.productionTips = false //阻止vue在启动时生成生产提示 26 new Vue({ 27 el:'#root', 28 data:{ 29 keyword:'', 30 sortType:0, //0代表原序 1 降序 2升序 31 personArr:[ 32 {id:'001',name:'马冬梅',age:28,sex:'女'}, 33 {id:'002',name:'张冬梅',age:19,sex:'女'}, 34 {id:'003',name:'周杰伦',age:30,sex:'男'}, 35 {id:'004',name:'谢柏伦',age:21,sex:'男'}, 36 ] 37 }, 38 computed:{ 39 filpersons(){ 40 const arr = this.filpersons = this.personArr.filter((p) =>{ 41 return p.name.indexOf(this.keyword) !== -1 42 }) 43 //判断一下是否需要排序 44 if(this.sortType){ 45 arr.sort((p1,p2)=>{ 46 return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age 47 }) 48 } 49 return arr 50 } 51 } 52 }) 53 54 </script> 55 </html>