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

目录

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

具体代码如下所示:

<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

<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

<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

<div id="root">
	<ul>
        <li v-for="(number,index) of 5" :key="index">
            {{index}} - {{number}}
        li>
    ul>
div>

1.5 案例整合

<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 错误案例

<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. 在浏览器中打开案例,之后在输入框中输入一些内容

第8集丨Vue 江湖 —— 列表渲染_第1张图片

  1. 点击添加按钮,此时会发现输入框已经错乱了。

第8集丨Vue 江湖 —— 列表渲染_第2张图片

2.3.3 错乱原理图

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

第8集丨Vue 江湖 —— 列表渲染_第3张图片

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

第8集丨Vue 江湖 —— 列表渲染_第4张图片

2.4 开发中如何选择key?

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

三、列表过滤

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

第8集丨Vue 江湖 —— 列表渲染_第5张图片

3.1 watch实现

  • 列表显示:使用 v-for指令遍历数组persons
  • data中定义属性filPersons:存放过滤后的内容
  • 使用数组filter方法实现过滤
<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方法实现过滤
<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 需求

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

第8集丨Vue 江湖 —— 列表渲染_第6张图片

4.2 实现

  • 定义sortType属性:2升序、1降序、0原顺序
  • 数组sort方法:arr.sort(a,b)a-b为升序,b-a为降序
<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>

你可能感兴趣的:(Vue2江湖,vue.js,javascript,前端)