Vue2基础 09:列表渲染

1 基本列表

我们可以使用 v-for 指令基于一个数组来渲染一个列表。
与react类似,用了遍历生成同样结构的多个数据,必须要每个数据都起个名字/打个标识–key。

写法
v-for 指令的值需要使用 item in items 形式的特殊语法,其中 items 是源数据的数组,而 item 是迭代项的别名,也就是形参:

const items = ref([{ message: 'Foo' }, { message: 'Bar' }])

<li v-for="item in items">
  {{ item.message }}
</li>

这里item即为key,也就是形参。

1.1遍历数组

<body>
    <div id="root">
    <!--遍历数组-->
        <h2>人员列表</h2>
        <ul>
            <li v-for="p in persons" :key="p.id">{{p.name}}-{{p.age}}</li>
        </ul>
    </div>
</body>
<script type="text/javascript">
    new Vue({
        el:'#root',  
        data:{ 
            persons:[
                {id:'001',name:'张三',age:19},
                {id:'002',name:'李四',age:20},
                {id:'003',name:'王五',age:21}
            ],
        }
    })
</script>

这里p为形参。

v-for 也支持使用可选的第二个参数表示当前项的位置索引:
<li v-for="(p,index) in persons" :key="index">{{p.name}}-{{p.age}}</li>

in 可以换成 of 作为分隔符:
<li v-for="(p,index) of persons" :key="index">{{p.name}}-{{p.age}}</li>

1.2 遍历对象

可以使用 v-for 来遍历一个对象的所有属性。遍历的顺序会基于对该对象调用 Object.keys() 的返回值来决定。

        <h2>汽车信息</h2>
        <ul>
            <li v-for="(value,key) of car" :key="key">{{key}}:{{p.value}}</li>
        </ul>
        
 		car:{
                name:'奥运',
                price:'50万',
                color:'黑色'
            },

三个参数(属性值,属性名,位置索引):
v-for="(value, key, index) in car

1.3 遍历字符串

        <h2>汽车信息</h2>
        <ul>
            <li v-for="(char,index) of str" :key="index">{{char}}-{{index}}</li>
        </ul>
        str:'hello'
        

1.4 遍历指定次数

v-for 可以直接接受一个整数值。

        <h2>汽车信息</h2>
        <ul>
            <li v-for="(number,index) of 5" :key="index">{{index}}-{{number}}</li>
        </ul>

注意此处 n 的初值是从 1 开始而非 0。

2 key的作用与原理

为了给 Vue 一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,需要为每个元素对应的块提供一个唯一的 key。

下面通过一个案例来探索key是如何起作用的。在上面1.1的基础上,点击按钮persons新增一个,且自动在后面添加一个文本框。

<body>
    <div id="root">
    <!--遍历数组-->
        <h2>人员列表</h2>
        <button @click.once="add">添加一个老刘</button>
        <ul>
            <li v-for="(p,index) of persons" :key="p.id">
                {{p.name}}-{{p.age}}
                <input type="text">
            </li>
            <!--- 若key写"index"或者不写都会导致新增信息和文本框错位---->
        </ul>
    
    </div>
</body>

<script type="text/javascript">
    new Vue({
        el:'#root',  
        data:{ 
            persons:[
                {id:'001',name:'张三',age:19},
                {id:'002',name:'李四',age:20},
                {id:'003',name:'王五',age:21}
            ]
        },
        methods:{
            add(){
                const p = {id:'004',name:'老刘',age:23}
                this.persons.unshift(p)
                //在数组的前端添加项
            }
        }
    })
</script>

模板中的所有元素的key在Vue征用后,生成真实DOM后不显示了
新虚拟DOM先与初始虚拟DOM进行对比,将不同的节点转为新真实DOM
若没有key,Vue自动将index作为key的值

小结

  1. 虚拟DOM中key的作用:key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下。
  2. 对比规则:
  • 旧虚拟DOM中找到了与新虚拟DOM相同的key
    (1)若内容没变,直接使用之前的真实DOM
    (2)若内容变了,则生成新的真实DOM,随后替换调页面中之前的真实DOM
  • 旧虚拟DOM中未找到与新虚拟DOM相同的key
    (1)创建新的真实DOM,随后渲染到页面
  1. 用index作为key可能会引发的问题:
    (1)若对数据进行逆序添加、逆序 删除等破坏顺序的操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低
    (2)若结构中包含输入类DOM:会产生错误DOM更新 ==> 界面有问题
  2. 开发中如何选择key:
    (1)最好使用每条数据的唯一标志作为key
    (2)若不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的

3 列表过滤——模糊搜索

<body>
    <div id="root">
        <h2>人员列表</h2>
        <input type="text" placeholder="请输入名字" v-model="keyword">
        <ul>
            <li v-for="(p,index) of filpersons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}</li>
        </ul>
    </div>
</body>

<script type="text/javascript">
    new Vue({
        el:'#root',  
        data:{ 
            keyword:'',
            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:'男'}
            ],
            
        }
    })
</script>

3.1 用侦听属性(监视属性)监视keyword是否改变

<li v-for="(p,index) of filpersons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}</li>
//数组改为filpersons
data:{
    filpersons:[] //添加数组 filpersons
}
watch:{
    keyword:{
        immediate.true,//先调一次
        handler(newvalue){
            this.filpersons = this.persons.filter((p)=>{
                return p.name.indexOf(newvalue) !== -1
                //p为形参
                //return 后面是匹配的条件
            })
        }
    }
}

filter( ):返回值为数组,其为符合条件的所有元素,即数组元素是调用的数组的子集。若无符合条件的元素,则返回空数组
indexOf:用于查找子字符串再字符串中的位置:返回第一次出现的位置;若无则返回-1;若查找空字符串,则返回0。

3.2 用计算属性实现(更好

computed:{
    filpersons(){
        return this.persons.filter((p)=>{
            return p.name.indexOf(this.keyword) !== -1
        })
    }
}

4 列表排序

有时,我们希望显示过过滤或排序后的内容,而不实际变更或重置原始数据。

案例 在上面3的基础上,新增按钮,点击可按照年龄进行排序,还可以恢复最开始的顺序。
在这里插入图片描述

新增3个按钮,并绑定对应的事件。

<body>
    <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) of filpersons" :key="index">
            	{{p.name}}-{{p.age}}-{{p.sex}}
            </li>
        </ul>
    </div>
</body>

利用计算属性来返回排序后的内容。

<script type="text/javascript">
    new Vue({
        el:'#root',  
        data:{ 
            keyword:'',
            sortType:0, //0 原顺序,1 降序,2 升序
            persons:[
                {id:'001',name:'马冬梅',age:36,sex:'女'},
                {id:'002',name:'周冬雨',age:25,sex:'女'},
                {id:'003',name:'周杰伦',age:45,sex:'男'},
                {id:'004',name:'温兆伦',age:18,sex:'男'}
            ],
        },
        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>

sort( )函数用法

若点击年龄降序 按钮,sortType = 1,计算属性重新计算,三元表达式返回 p2.age-p1.age,sort函数按照降序排。升序同理。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值