12.列表渲染
12.1.列表渲染
v-for指令:
1.用于展示列表数据
2.语法:v-for="(item,index) in xxx" :key="yyy"
3.可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
< body>
< div id= "root" >
< ! -- 遍历列表 -- >
< h3> 人员列表< / h3>
< ul>
< ! -- < li v- for = "p in persons" : key= "p.id" >
{ { p. name} } - { { p. age} }
< / li> -- >
< li v- for = "(p,index) in persons" : key= "index" >
{ { p. name} } - { { p. age} }
< / li>
< / ul>
< ! -- 遍历对象 -- >
< h3> 汽车信息< / h3>
< ul>
< li v- for = "(value,key) of car" : key= "key" >
{ { key} } : { { value} }
< / li>
< / ul>
< ! -- 遍历字符串 -- >
< h3> 测试遍历字符串 ( 用的少) < / h3>
< ul>
< li v- for = "(char,index) of str" : key= "index" >
{ { char} } - { { index} }
< / li>
< / ul>
< h3> 遍历指定次数 ( 用的少< / h3>
< ul>
< li v- for = "(number,index) of 5" : key= "index" >
{ { number} } - { { index} }
< / li>
< / ul>
< / div>
< script>
Vue. config. productionTip = false ;
new Vue ( {
el : '#root' ,
data : {
persons : [
{ id : '001' , name : '张三' , age : 18 } ,
{ id : '002' , name : '李四' , age : 19 } ,
{ id : '003' , name : '王五' , age : 20 } ,
] ,
car : {
name : '领克' ,
price : '30w' ,
color : '白色'
} ,
str : 'hello'
}
} )
< / script>
< / body>
12.2.key的原理
面试题: react、vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中key的作用:
key是虚拟DON对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DoA】,
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
1].若虚拟DOM中内容没变,直接使用之前的真实DOM !
2].若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM.
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:
1.若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
2如果结构中还包含输入类的DOM:
会产生错误DOM更新==>界面有问题。
4。开发中如何选择key? :
1.最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。
12.3.列表过滤
< body>
< div id= "root" >
< h3> 人员列表< / h3>
< input type= "text" placeholder= "请输入名字:" v- model= "keyWord" >
< ul>
< li v- for = "(p,index) of filterPersons" : key= "p.id" >
{ { p. name} } - { { p. age} } -- { { p. sex} }
< / li>
< / ul>
< / div>
< script>
Vue. config. productionTip = false ;
new Vue ( {
el : '#root' ,
data : {
keyWord : '' ,
persons : [
{ id : '001' , name : '马冬梅' , age : 18 , sex : '女' } ,
{ id : '002' , name : '周冬雨' , age : 19 , sex : '女' } ,
{ id : '003' , name : '周杰伦' , age : 20 , sex : '男' } ,
{ id : '004' , name : '温兆伦' , age : 21 , sex : '男' } ,
]
} ,
computed : {
filterPersons ( ) {
return this . persons. filter ( ( p ) => {
return p. name. indexOf ( this . keyWord) !== - 1 ;
} )
}
}
} )
< / script>
< / body>
12.4.列表排序
< body>
< div id= "root" >
< h3> 人员列表< / h3>
< 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) of filterPersons" : key= "p.id" >
{ { p. name} } - { { p. age} } -- { { p. sex} }
< / li>
< / ul>
< / div>
< script>
Vue. config. productionTip = false ;
new Vue ( {
el : '#root' ,
data : {
keyWord : '' ,
sortType : 0 ,
persons : [
{ id : '001' , name : '马冬梅' , age : 28 , sex : '女' } ,
{ id : '002' , name : '周冬雨' , age : 19 , sex : '女' } ,
{ id : '003' , name : '周杰伦' , age : 16 , sex : '男' } ,
{ id : '004' , name : '温兆伦' , age : 21 , sex : '男' } ,
]
} ,
computed : {
filterPersons ( ) {
const arr = this . persons. filter ( ( p ) => {
return p. name. indexOf ( this . keyWord) !== - 1 ;
} )
if ( this . sortType) {
arr. sort ( ( p1, p2 ) => {
return this . sortType === 1 ? p2. age - p1. age : p1. age - p2. age;
} )
}
return arr;
}
}
} )
< / script>
< / body>
12.5.更新时的一个问题
< body>
< div id= "root" >
< h3> 人员列表< / h3>
< button @click= "updateMei" > 更新马冬梅信息< / button>
< ul>
< li v- for = "(p,index) of persons" : key= "p.id" >
{ { p. name} } - { { p. age} } -- { { p. sex} }
< / li>
< / ul>
< / div>
< script>
Vue. config. productionTip = false ;
new Vue ( {
el : '#root' ,
data : {
persons : [
{ id : '001' , name : '马冬梅' , age : 28 , sex : '女' } ,
{ id : '002' , name : '周冬雨' , age : 19 , sex : '女' } ,
{ id : '003' , name : '周杰伦' , age : 16 , sex : '男' } ,
{ id : '004' , name : '温兆伦' , age : 21 , sex : '男' } ,
]
} ,
methods : {
updateMei ( ) {
this . persons[ 0 ] = { id : '001' , name : '马老师' , age : 30 , sex : '男' } ;
}
} ,
} )
< / script>
< / body>
12.6.Vue.set的使用
< body>
< div id= "root" >
< h3> 学校信息< / h3>
< h5> 学校名称:{ { name} } < / h5>
< h5> 学校地址:{ { address} } < / h5>
< hr>
< h3> 学生信息< / h3>
< button @click= "addSex" > 添加一个性别属性< / button>
< h4> 姓名:{ { student. name} } < / h4>
< h4 v- if = "student.sex" > 性别:{ { student. sex} } < / h4>
< h4> 年龄:真实{ { student. age. realAge} } , 对外{ { student. age. shuoAge} } < / h4>
< h3> 朋友们< / h3>
< ul>
< li v- for = "(f,index) of student.friends" : key= "index" >
{ { f. name} } - { { f. age} }
< / li>
< / ul>
< / div>
< script>
Vue. config. productionTip = false ;
const vm = new Vue ( {
el : '#root' ,
data : {
name : '东华理工大学' ,
address : '南昌' ,
student : {
name : 'tom' ,
age : {
realAge : 35 ,
shuoAge : 18
} ,
friends : [
{ name : 'jack' , age : 29 } ,
{ name : 'jerry' , age : 27 }
]
}
} ,
methods : {
addSex ( ) {
this . $set ( this . student, 'sex' , '女' ) ;
}
}
} )
< / script>
< / body>
12.7.总结Vue数据监控
Vue监视数据的原理:
1.vue会监视data中所有层次的数据。
2.如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理
(2).如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)
或 vm.$set(target,propertyName/index,value)
3.如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1).调用原生对应的方法对数组进行更新。
(2).重新解析模板,进而更新页面。
4.在Vue修改数组中的某个元素一定要用如下方法:
1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2.vue.set()或vm.$set()
特别注意:Vue.set()和vm.$set()不能给vm或 vm的根数据对象添加属性
< body>
< div id= "root" >
< button @click= "student.age.realAge++" > 年龄+ 1 < / button> < br>
< button @click= "addSex" > 添加一个性别属性< / button> < br>
< button @click= "student.sex='未知' " > 修改性别< / button> < br>
< button @click= "addFriend" > 在列表首位添加一个朋友< / button> < br>
< button @click= "updateFirstFriendName" > 修改第一个朋友名字为:张三< / button> < br>
< button @click= "addHobby" > 添加一个爱好< / button> < br>
< button @click= "updateFirstHobby" > 修改第一个爱好为:长跑< / button> < br>
< h3> 学校信息< / h3>
< h5> 学校名称:{ { name} } < / h5>
< h5> 学校地址:{ { address} } < / h5>
< hr>
< h3> 学生信息< / h3>
< h4> 姓名:{ { student. name} } < / h4>
< h4 v- if = "student.sex" > 性别:{ { student. sex} } < / h4>
< h4> 年龄:真实{ { student. age. realAge} } , 对外{ { student. age. shuoAge} } < / h4>
< h3> 爱好:< / h3>
< ul>
< li v- for = "(h,index) in student.hobby" : key= "index" >
{ { h} }
< / li>
< / ul>
< h3> 朋友们< / h3>
< ul>
< li v- for = "(f,index) of student.friends" : key= "index" >
{ { f. name} } - { { f. age} }
< / li>
< / ul>
< / div>
< script>
Vue. config. productionTip = false ;
const vm = new Vue ( {
el : '#root' ,
data : {
name : '东华理工大学' ,
address : '南昌' ,
student : {
name : 'tom' ,
age : {
realAge : 35 ,
shuoAge : 18
} ,
hobby : [ '抽烟' , '喝酒' , '烫头' ] ,
friends : [
{ name : 'jack' , age : 29 } ,
{ name : 'jerry' , age : 27 }
]
}
} ,
methods : {
addSex ( ) {
this . $set ( this . student, 'sex' , '女' ) ;
} ,
addFriend ( ) {
this . student. friends. unshift ( { name : 'kiadt' , age : 19 } ) ;
} ,
updateFirstFriendName ( ) {
this . student. friends[ 0 ] . name = '张三' ;
} ,
addHobby ( ) {
this . student. hobby. push ( '撑杆跳' ) ;
} ,
updateFirstHobby ( ) {
this . $set ( this . student. hobby, 0 , '长跑' ) ;
}
}
} )
< / script>
< / body>