Vue---条件渲染(v-if、v-show)、列表渲染(v-for)、列表中key的原理和作用、列表过滤(filter)、列表排序(sort) た 入场券 2024-04-07 11:52 9阅读 0赞 **目录** 一、条件渲染 1.v-if 2.v-show 3.template 二、列表渲染 1.v-for 遍历数组 遍历对象 遍历字符串 遍历指定次数 三、v-for中key作用和原理 情景 改正 总结key 1.虚拟DOM中key的作用 2.对比规则 3.用index作为key可能引发的问题 4.开发中如何选择key? 四、列表过滤 1.watch案例 2.computed案例 五、列表排序 -------------------- ## 一、条件渲染 ## 当符合某个条件后,我们就选用某种样式 ### 1.v-if ### 适用于:切换频率较低的场景 特点:不展示的DOM元素直接被移除,在页面源码中无法看到 注意:v-if,v-else-if 、 else if,div要紧紧的挨在一起,不能打断 - <!-- v-else-if 类似java中if else if判断 --> <!-- 这四个div要紧紧的挨在一起,不能打断 --> <div v-if="n===1" >Angular</div> <div v-else-if="n===2" >React</div> <div v-else-if="n===3" >Vue</div> <div v-else >6666666</div> <!-- 使用v-if做条件渲染:在网页查看源码时,将不会看到下面这个html语句 --> <h2 v-if="false">欢迎来到{ {name}}学习</h2> ### 2.v-show ### 写法:v-show=“表达式” 适用于:切换频率较高的场景 特点:不展示DOM元素未被移除,仅仅是使用上市隐藏掉 备注:使用v-if时,元素可能无法获取到,而使用v-show一定可以获取到 <!-- 使用v-show做条件渲染:确切的说这个底层是display:none --> <h2 v-show="false">欢迎来到{ {name}}学习</h2> ### 3.template ### 当我们对某几个标签添加相同的样式的时候,我们就可以使用template标签,在标签上添加v-if属性 好处:不影响整体样式。 备注:template标签不影响整体结构,只是把下面这三个标签给包裹起来,在页面查看源码的时候也不会发现template标签 **此标签只能使用v-if,不能使用v-show** <!-- template标签不影响整体结构,只是把下面这三个标签给包裹起来,在页面查看源码的时候也不会发现template标签 此标签只能使用v-if,不能使用v-show --> <template v-if="n===1"> <h2>你好</h2> <h2>中国</h2> <h2>北京</h2> </template> ## 二、列表渲染 ## ### 1.v-for ### 用于展示列表数据 语法:v-for="(item,index) in xxx" :key="yyy" 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少) #### 遍历数组 #### v-for类似java中foreach遍历,persons里面有几个值,我们在页面就会呈现几个 :key="p.id"让每一个li都有一个唯一的标识,类似数据库中的主键 \{ \{p\}\} 这么输出的话,会把数据直接输出,我们一般不这样 <li v-for="p in persons" :key="p.id"> <!-- { {p}} 这么输出的话,会把数据直接输出,我们一般不这样 --> { {p.name}}-{ {p.age}} </li> index就是索引值,这个地方会有索引值,类似数组的下标 :key="p.id" 这个地方不用p.id也可以,我们使用index ,因为index也是唯一的,类似数组下标 :key这个标签特别重要,动态绑定数据 <ul> <li v-for="(p,index) in persons" :key="index"> <!-- { {p}} 这么输出的话,会把数据直接输出,我们一般不这样 --> { {p.name}}-{ {p.age}}-{ {index}} </li> </ul> 如果要有顺序的话,就需要数组来存储 这里的id类似数据库中的主键 data:{ persons:[ {id:'001',name:'张三',age:18}, {id:'002',name:'李四',age:18}, {id:'003',name:'王五',age:20} ] }, ![66105053125b4fed9803629026fb0e1b.png][] #### 遍历对象 #### 这里的对象直接就是value,不用和数组一样调用了 <h2>汽车信息</h2> <ul> <li v-for="(value,k) in car" :key="k" > { {value}}-{ {k}} </li> </ul> data:{ car:{ name:'奥迪A8', price:"666666", color:'黑色' } }, ![245964d95ba54757861f429939f47309.png][] #### 遍历字符串 #### <ul> <li v-for="(value,k) in str" :key="k" > { {value}}-{ {k}} </li> </ul> data:{ str:'hello' } ![3b60c747db01406bb97ee6e0210993bd.png][] #### 遍历指定次数 #### <ul> <li v-for="(number,index) in 5" :key="index" > { {number}}-{ {index}} </li> </ul> ![acc04a907d554545978e8bdf9fe97c95.png][] ## 三、v-for中key作用和原理 ## 如果在写代码时并**没有指定:key**,我们会把**index默认**的作为key 通过我们查看发现,我们在**源代码中是有:key**的,但是在**网页上并不会显示**,原因就是这个:**key是vue内部在用,用完就干掉了** ![d774e0b7092643bab03369238f202b2d.png][] ### 情景 ### 如下,当我们下边代码 :**key**的**值**是**index**的时候,会出现**一系列的问题(不同的情景不一样,可能index不会出问题)** <h2>人员列表</h2> <button @click="add">添加一个老刘</button> <ul> <li v-for="(p,index) in persons" :key="index"> <!-- { {p}} 这么输出的话,会把数据直接输出,我们一般不这样 --> { {p.name}}-{ {p.age}}-{ {index}} <input type="text"> </li> </ul> ![153c3489b710478e8fd9d14aee7fe2ce.png][] 当我们在输入框中输入好内容,**点击“添加一个老刘”**,就会出现下列情况,**文本框不会随着人名流动** ![76467c55fab141e89a600cfde5985b78.png][] ![09a173e7a90b49f486e8c40e98b15eda.png][] #### 改正 #### 我们**修改**一下代码 **:key="p.id",**我们再运行一下程序就**不会发生这种情况(正常运行)** <h2>人员列表</h2> <button @click="add">添加一个老刘</button> <ul> <!-- index就是索引值,这个地方会有索引值,类似数组的下标 --> <!-- :key="p.id" 这个地方不用p.id也可以,我们使用index ,因为index也是唯一的,类似数组下标-->、 <!-- :key这个标签特别重要,动态绑定数据 --> <li v-for="(p,index) in persons" :key="p.id"> <!-- { {p}} 这么输出的话,会把数据直接输出,我们一般不这样 --> { {p.name}}-{ {p.age}}-{ {index}} <input type="text"> </li> </ul> ![e27d1ae5c03547e9ad70edafd48eed40.png][] ![f219c039c1cb43cdb3bc5baaa26b4d25.png][] ### 总结key ### #### 1.虚拟DOM中key的作用 #### key是虚拟对象的标识,当**数据发生变化**时,Vue会根据新数据**生成新的虚拟DOM**,随后Vue进行**新虚拟DOM与旧虚拟DOM**的差异**比较**。 #### 2.对比规则 #### ①旧虚拟DOM**找到了**与新虚拟DOM相同的key: 若虚拟DOM中**内容没变**,**直接使用之前**的真实DOM 若虚拟DOM中**内容变了**,则**生成新的真实DOM**,随后**替换**掉页面中**之前**的真实DOM ②旧虚拟DOM中**未找到**与新虚拟DOM中相同的key **创建新**的真实DOM,随后渲染到页面 #### 3.用index作为key可能引发的问题 #### ①若对数据进行逆序添加、逆序删除等破坏顺序操作: **会产生没有必要的真实DOM更新**==》界面效果没问题,**但效率低** ②如果结构中还包含输入类DOM: 会产生错误DOM更新==》界面有问题 #### 4.开发中如何选择key? #### ①最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等(类似数据库中主键) ②如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表用于展示,使用index作为key是没有问题的 ## 四、列表过滤 ## ### 1.watch案例 ### 使用**watch监视keyWords** 初始界面: ![0b4054fef01b4a03831249beb27baf5b.png][] 当我们随便在框内输入时,下面就会显示我们想要查找的内容 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> 初识vue</title> <!--引入vue 引入之后,全局就多了一个vue这个构造函数--> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <ul> <h2>人员列表</h2> <!-- 双向绑定一下 --> <input type="text" placeholder="请输入名字" v-model="keyWords"> <li v-for="(p,index) in filPersons" :key="p.id" > { {p.name}}-{ {p.age}}-{ {p.sex}} </li> </ul> </div> <script type="text/javascript"> //阻止vue在启动时生成生产提示 Vue.config.productionTip=false new Vue({ el:'#root', data:{ keyWords:'', 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:{ // 监视谁我们就写谁 keyWords:{ // 初始化时让handler调用一下,如果不调用的话,初始页面会没有内容 // 前提条件:所有的字符串.indexOf("")空字符串,返回值都是0 immediate:true, handler(newValue,oldValue){ // 过滤 // filter规律之后,并不会影响我们初始的数组,而是生成一个全新的数组 // 我们不能更改直接赋值到原数组,否则会导致我们查询的内容越来越少,最后甚至没有了 this. filPersons= this.persons.filter((p)=>{ // 函数体 // return 后面加的语句使我们要的数据 // indexOf 方法,当含有括号内的字符串的时候,会返回下标是第几位(从零开始算 // 当不包含的时候,就会返回-1 return p.name.indexOf(newValue) !==-1 }) } } }, methods:{ } }) </script> </body> </html> ### 2.computed案例 ### <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> 初识vue</title> <!--引入vue 引入之后,全局就多了一个vue这个构造函数--> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <ul> <h2>人员列表</h2> <!-- 双向绑定一下 --> <input type="text" placeholder="请输入名字" v-model="keyWords"> <li v-for="(p,index) in filPersons" :key="p.id" > { {p.name}}-{ {p.age}}-{ {p.sex}} </li> </ul> </div> <script type="text/javascript"> //阻止vue在启动时生成生产提示 Vue.config.productionTip=false const vm= new Vue({ el:'#root', data:{ keyWords:'', 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:{ // 这个形式是缩写,当getter函数使用 // 初次读取的时候会调用一下,当依赖的数据发生变化时也会调用一下 filPersons(){ // 这个return是计算属性规定的 return this.persons.filter((p)=>{ // 这个return是filter规定的 return p.name.indexOf(this.keyWords) !==-1 }) } } }) </script> </body> </html> **效果相同** ## 五、列表排序 ## <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> 初识vue</title> <!--引入vue 引入之后,全局就多了一个vue这个构造函数--> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <h2>人员列表</h2> <!-- 双向绑定一下 --> <input type="text" placeholder="请输入名字" v-model="keyWords"> <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 type="text/javascript"> //阻止vue在启动时生成生产提示 Vue.config.productionTip=false const vm= new Vue({ el:'#root', data:{ keyWords:'', // 0原顺序 1降序 2升序 sortType:0, 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:{ // 这个形式是缩写,当getter函数使用 // 初次读取的时候会调用一下,当依赖的数据发生变化时也会调用一下 filPersons(){ // 我们把这个地方的return取消,不着急return const arr= this.persons.filter((p)=>{ // 这个return是filter规定的 return p.name.indexOf(this.keyWords) !==-1 }) if(this.sortType){ // 运行到这里说明不是0 arr.sort( (p1,p2)=>{ // 三目运算 return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age }) } //当 this.sortType===0时,会直接跳过if来到这里(原始数据不会改变,所以就是原顺序 return arr } } }) </script> </body> </html> 原顺序: ![2c42172d9026424d9387e040f0fbd31c.png][] 升序: ![a2232be8c9174b1ba78d6c5c34512b89.png][] 降序![ac9868813c7149b1ac663b7997f34956.png][] [66105053125b4fed9803629026fb0e1b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/d541c22433374d8da6021af7bab85839.png [245964d95ba54757861f429939f47309.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/bc64b7e935144cd7aa8f41f0ab8064f4.png [3b60c747db01406bb97ee6e0210993bd.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/4de7affce1fc414190cfe00f1c36c554.png [acc04a907d554545978e8bdf9fe97c95.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/1c26bd88e1ef4f0bb629e58d6fd4d7fb.png [d774e0b7092643bab03369238f202b2d.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/51f896084a5f433bbc086be13850206b.png [153c3489b710478e8fd9d14aee7fe2ce.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/84e09d21af8d44d6939a9ced907e9b4b.png [76467c55fab141e89a600cfde5985b78.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/71224d6ffab0478f856f2b2b8b04b107.png [09a173e7a90b49f486e8c40e98b15eda.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/24ebd9f25ef647d1b019e777b17e5900.png [e27d1ae5c03547e9ad70edafd48eed40.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/a8a7794db25843e08de1511fba831c63.png [f219c039c1cb43cdb3bc5baaa26b4d25.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/fb2c44bc21f84382b560b41110d12966.png [0b4054fef01b4a03831249beb27baf5b.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/7b27bc029228460699887ecbe865c563.png [2c42172d9026424d9387e040f0fbd31c.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/94be9dc9e833485fa1b48e758484a6c0.png [a2232be8c9174b1ba78d6c5c34512b89.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/74f27957f93745da826249184f9aad90.png [ac9868813c7149b1ac663b7997f34956.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/07/c1c0ffae0538468cb90fbd81351efa46.png
还没有评论,来说两句吧...