第8集丨Vue 江湖 —— 列表渲染

目录

  • 一、v-for指令
    • [1.1 遍历数组](#1.1 遍历数组)
    • [1.2 遍历对象](#1.2 遍历对象)
    • [1.3 遍历字符串](#1.3 遍历字符串)
    • [1.4 遍历指定次数](#1.4 遍历指定次数)
    • [1.5 案例整合](#1.5 案例整合)
  • 二、key的作用与原理
    • [2.1 虚拟DOM中key的作用](#2.1 虚拟DOM中key的作用)
    • [2.2 新旧虚拟DOM对比规则](#2.2 新旧虚拟DOM对比规则)
    • [2.3 用index作为key可能会引发的问题](#2.3 用index作为key可能会引发的问题)
      • [2.3.1 错误案例](#2.3.1 错误案例)
      • [2.3.2 错误效果](#2.3.2 错误效果)
      • [2.3.3 错乱原理图](#2.3.3 错乱原理图)
    • [2.4 开发中如何选择key?](#2.4 开发中如何选择key?)
  • 三、列表过滤
    • [3.1 watch实现](#3.1 watch实现)
    • [3.2 computed计算属性实现](#3.2 computed计算属性实现)
  • 四、列表排序
    • [4.1 需求](#4.1 需求)
    • [4.2 实现](#4.2 实现)

一、v-for指令

  1. 用于展示列表数据
  2. 语法v-for="(item, index) in/of xxx" :key="yyy"
  3. 可遍历:数组、对象、字符串、指定次数。

1.1 遍历数组

下面案例中,定义了一个数组persons , 我们使用v-for指令进行遍历,遍历的次数即为数组的长度length

接受的参数有两个,一个是数组中的每一项p,另一个参数为数组的索引值index,并用:key动态指定每一项的唯一标识key

注意 :这里的唯一标识key不会在真实DOM上,但是会在Vue生成的虚拟DOM上。在用DIFF算法的时候会用到。

具体代码如下所示:

html 复制代码
<div id="root">
	<ul>
	    <li v-for="(p,index) in persons" :key="index">
	        {{p.name}} - {{p.use}}
	    </li>
	</ul>
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            persons:[
                {id:'001',name:'令狐冲',use:"独孤九剑"},
                {id:'002',name:'任盈盈',use:"仙女下凡"},
                {id:'003',name:'任我行',use:"吸星大法"}
            ]
        }
        
    })
</script>

1.2 遍历对象

下面案例中,定义了一个对象person , 我们使用v-for指令进行遍历,遍历的次数即为对象的属性的个数。

接受的参数有两个,一个是对象中的每个属性的值value,另一个参数为对象的属性名key,并用:key动态指定每一项的唯一标识key

html 复制代码
<div id="root">
	<ul>
        <li v-for="(value,key) of person" :key="key">
            {{key}} - {{value}}
        </li>
    </ul>
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            person:{
                name:'令狐冲',
                use:'独孤九剑',
                menpai:'华山派'
            }
        }
        
    })
</script>

1.3 遍历字符串

下面案例中,定义了一个字符串str , 我们使用v-for指令进行遍历,遍历的次数即为字符串的字符个数。

接受的参数有两个,一个是字符串中的每个字符值char,另一个参数为字符串的索引index,并用:key动态指定每一项的唯一标识key

html 复制代码
<div id="root">
	<ul>
        <li v-for="(char,index) of str" :key="index">
            {{index}} - {{char}}
        </li>
    </ul>
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            str:'笑傲江湖'
        }
        
    })
</script>

1.4 遍历指定次数

下面案例中,指定遍历次数为5次,我们使用v-for指令进行遍历。

接受的参数有两个,一个是数值number,另一个参数为索引index,并用:key动态指定每一项的唯一标识key

html 复制代码
<div id="root">
	<ul>
        <li v-for="(number,index) of 5" :key="index">
            {{index}} - {{number}}
        </li>
    </ul>
</div>

1.5 案例整合

html 复制代码
<div id="root">
    <h2>遍历数组</h2>
    <ul>
        <li v-for="(p,index) in persons" :key="index">
            {{p.name}} - {{p.use}}
        </li>
    </ul>
    
    <h2>遍历对象</h2>
    <ul>
        <li v-for="(value,key) of person" :key="key">
            {{key}} - {{value}}
        </li>
    </ul>

    <h2>遍历字符串:'笑傲江湖'</h2>
    <ul>
        <li v-for="(char,index) of str" :key="index">
            {{index}} - {{char}}
        </li>
    </ul>

    <h2>遍历指定次数:5次</h2>
    <ul>
        <li v-for="(number,index) of 5" :key="index">
            {{index}} - {{number}}
        </li>
    </ul>
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            persons:[
                {id:'001',name:'令狐冲',use:"独孤九剑"},
                {id:'002',name:'任盈盈',use:"仙女下凡"},
                {id:'003',name:'任我行',use:"吸星大法"}
            ],
            person:{
                name:'令狐冲',
                use:'独孤九剑',
                menpai:'华山派'
            },
            str:'笑傲江湖'
        }
        
    })
</script>

二、key的作用与原理

2.1 虚拟DOM中key的作用

  • key是虚拟DOM对象的唯一标识
  • 当状态中的数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM
  • 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异进行比较。

2.2 新旧虚拟DOM对比规则

  • 旧虚拟DOM中找到了与新虚拟DOM相同的key:

     ⅰ. 若【虚拟DOM】中内容没变,直接使用之前的【真实DOM】 !
     ⅱ. 若【虚拟DOM】中内容变了,则生成【新的真实DOM】,随后替换掉页面中【之前的真实DOM】.
    
  • 旧虚拟DOM中未找到与新虚拟DOM相同的key

      ⅰ. 创建【新的真实DOM】,随后渲染到到页面。
    

2.3 用index作为key可能会引发的问题

  • 若对数据进行:逆序添加逆序删除破坏顺序操作:

    ⅰ. 会产生没有必要的【真实DOM】更新==>界面效果没问题,但效率低。
    
  • 如果结构中还包含输入类的DOM:

      i . 会产生【错误DOM】更新==>界面有问题。
    

2.3.1 错误案例

html 复制代码
<div id="root">
    <h2>index作为key引发的问题</h2>
    <button @click.once="add">在列表最前面:添加一个小六六</button>
    <ul>
        <li v-for="(p,index) in persons" :key="index">
            {{p.name}} - {{p.use}}
            <input type="text" >
        </li>
    </ul>
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            persons:[
                {id:'001',name:'令狐冲',use:"独孤九剑"},
                {id:'002',name:'任盈盈',use:"仙女下凡"},
                {id:'003',name:'任我行',use:"吸星大法"}
            ]
           
        },
        methods: {
            add() {
                this.persons.unshift({id:'004',name:'老六',use:'不会武功'})
            }
        },
        
    })
</script>

2.3.2 错误效果

  1. 在浏览器中打开案例,之后在输入框中输入一些内容
  1. 点击添加按钮,此时会发现输入框已经错乱了。

2.3.3 错乱原理图

  1. 遍历列表index作为key时,发生错乱原理图,如下所示:
  1. 遍历列表id作为key时,为什么没有发生错乱原理图,如下所示:

2.4 开发中如何选择key?

  • 最好使用每条数据的唯一标识作为key,比如id手机号身份证号学号唯一值
  • 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

三、列表过滤

需求:做一个列表过滤功能,UI如下图所示。在输入框中输入内容实现下面列表的过滤显示。

3.1 watch实现

  • 列表显示:使用 v-for指令遍历数组persons
  • data中定义属性filPersons:存放过滤后的内容
  • 使用数组filter方法实现过滤
html 复制代码
<div id="root">
    <h2>列表过滤</h2>
    <input type="text" placeholder="请输入内容" v-model="keyWord">
    <ul>
        <li v-for="(p,index) in filPersons" :key="index" >
            {{p.name}} - {{p.use}} - {{p.sex}}
        </li>
    </ul>
    
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            keyWord:'',
            persons:[
                {id:'001',name:'令狐冲',use:"独孤九剑",sex:'男'},
                {id:'002',name:'任盈盈',use:"仙女下凡",sex:'女'},
                {id:'003',name:'任我行',use:"吸星大法",sex:'男'}
            ],
            filPersons:[]
        },
        watch:{
            keyWord:{
                immediate:true,
                handler(value){
                    this.filPersons = this.persons.filter((p)=>{
                        return p.name.indexOf(value)>=0
                    })
                }
            }
        }
        
    })
</script>

3.2 computed计算属性实现

  • 列表显示:使用 v-for指令遍历数组persons
  • 定义计算属性filPersons:存放过滤后的内容
  • 使用数组filter方法实现过滤
html 复制代码
<div id="root">
    <h2>列表过滤</h2>
    <input type="text" placeholder="请输入内容" v-model="keyWord">
    <ul>
        <li v-for="(p,index) in filPersons" :key="index" >
            {{p.name}} - {{p.use}} - {{p.sex}}
        </li>
    </ul>
    
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            keyWord:'',
            persons:[
                {id:'001',name:'令狐冲',use:"独孤九剑",sex:'男'},
                {id:'002',name:'任盈盈',use:"仙女下凡",sex:'女'},
                {id:'003',name:'任我行',use:"吸星大法",sex:'男'}
            ]
        },
        computed:{
            filPersons(){
                return this.persons.filter((p)=>{
                    return p.name.indexOf(this.keyWord)!==-1
                })
            }
        }
    })
</script>

四、列表排序

4.1 需求

要求:在上述案例中,增加排序功能,分别为升序、降序功能

4.2 实现

  • 定义sortType属性:2升序、1降序、0原顺序
  • 数组sort方法:arr.sort(a,b)a-b为升序,b-a为降序
html 复制代码
<div id="root">
    <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.use}} - {{p.age}}
        </li>
    </ul>
    
</div>
<script>
    new Vue({
        el:'#root',
        data:{
            keyWord:'',
            sortType:0,
            persons:[
                {id:'001',name:'令狐冲',use:"独孤九剑",sex:'男',age:20},
                {id:'002',name:'任盈盈',use:"仙女下凡",sex:'女',age:19},
                {id:'003',name:'任我行',use:"吸星大法",sex:'男',age:50}
            ]
        },
        computed:{
            filPersons(){
                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>
相关推荐
夏河始溢4 分钟前
一七八、Node.js PM2使用介绍
前端·javascript·node.js·pm2
记忆深处的声音4 分钟前
vue2 + Element-ui 二次封装 Table 组件,打造通用业务表格
前端·vue.js·代码规范
陈随易5 分钟前
兔小巢收费引发的论坛调研Node和Deno有感
前端·后端·程序员
熊的猫20 分钟前
webpack 核心模块 — loader & plugins
前端·javascript·chrome·webpack·前端框架·node.js·ecmascript
速盾cdn27 分钟前
速盾:vue的cdn是干嘛的?
服务器·前端·网络
四喜花露水1 小时前
Vue 自定义icon组件封装SVG图标
前端·javascript·vue.js
前端Hardy1 小时前
HTML&CSS: 实现可爱的冰墩墩
前端·javascript·css·html·css3
web Rookie2 小时前
JS类型检测大全:从零基础到高级应用
开发语言·前端·javascript
Au_ust2 小时前
css:基础
前端·css
帅帅哥的兜兜2 小时前
css基础:底部固定,导航栏浮动在顶部
前端·css·css3