列表渲染,key作用与原理,列表过滤,列表排序

v-for指令:

  • 用于展示列表数据
  • 语法:<li v-for="(item, index) in xxx" :key="yyy">,其中key可以是index,也可以是遍历对象的唯一标识
  • 可遍历:数组、对象、字符串(用的少)、指定次数(用的少)

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <!--    遍历列表-->
    <h2>人员列表</h2>
    <ul>
        <li v-for="p in persons" :key="p.id">{{p.name}} - {{p.age}}</li>
    </ul>

    <!--    <h2>人员列表</h2>-->
    <!--    <ul>-->
    <!--        <li v-for="(p,index) in persons" :key="index">{{p.name}} - {{p.age}}</li>-->
    <!--    </ul>-->

    <!--    <h2>人员列表</h2>-->
    <!--    <ul>-->
    <!--        <li v-for="(a,b,c) in persons">{{a}} - {{b}} &#45;&#45; {{c}}</li>-->
    <!--    </ul>-->

    <!--    遍历对象-->
    <h2>汽车信息</h2>
    <ul>
        <li v-for="(value,k) in cars" :key="k">{{k}} -- {{value}}</li>
    </ul>

    <!--    遍历字符串-->
    <h3>测试遍历字符串</h3>
    <ul>
        <li v-for="(char,index) in strs" :key="index">
            {{char}} -- {{index}}
        </li>
    </ul>

    <!--    遍历指定次数-->
    <h2>测试遍历指定次数</h2>
    <ul>
        <li v-for="(number,index) in  5">{{number}} -- {{index}}</li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue({
        el: "#app",
        data: {
            persons: [
                {id: '001', name: '张三', age: 18},
                {id: '002', name: '李四', age: 19},
                {id: '003', name: '王五', age: 20}
            ],
            cars: {
                name: 'aodi',
                price: '18',
                color: 'balck'
            },
            strs: 'hello'
        }
    })
</script>
</body>
</html>

key作用与原理

react、vue中的key有什么作用?(key的内部原理)

虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:

对比规则:

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

若虚拟DOM中内容没变, 直接使用之前的真实DOM
若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到到页面

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

若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
 

开发中如何选择key?

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

image-20210718113900024

image-20210718114304512

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>人员列表</h2>
    <button @click.once="add">添加老刘</button>
    <ul>
        <h3>index作为key</h3>
        <!--        index作为key-->
        <li v-for="(p,index) in persons" :key="index">
            {{p.name}} - {{p.age}}<input type="text">
        </li>
    </ul>

    <ul>
        <!--        p.id作为key-->
        <h3>p.id作为key</h3>
        <li v-for="(p,index) in persons" :key="p.id">
            {{p.name}} - {{p.age}}<input type="text">
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue({
        el: "#app",
        data: {
            persons: [
                {id: '001', name: '张三', age: 18},
                {id: '002', name: '李四', age: 19},
                {id: '003', name: '王五', age: 20}
            ]
        },
        methods: {
            add() {
                const p = {id: '004', name: '老刘', age: 40}
                this.persons.unshift(p)
            }
        }
    })
</script>
</body>
</html>

列表过滤

方法一:使用监听属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入姓名" v-model="keyWord">
    <ul>
        <li v-for="(p,index) in filpersons" :key="p.id">
            {{p.name}} - {{p.age}} - {{p.sex}}
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue({
        el: "#app",
        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: '男'}
            ],
            filpersons: []
        },
        watch: {
            keyWord: {
                immediate: true,
                handler(newval) {
                    this.filpersons = this.persons.filter((p) => {
                        return p.name.indexOf(newval) !== -1
                    })
                }
            }
        }
    })
</script>
</body>
</html>

方法二:使用计算属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <h2>人员列表</h2>
    <input type="text" placeholder="请输入姓名" v-model="keyWord">
    <ul>
        <li v-for="(p,index) in filpersons" :key="p.id">
            {{p.name}} - {{p.age}} - {{p.sex}}
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue({
        el: "#app",
        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: '男'}
            ],
        },
        computed: {
            filpersons() {
                return this.persons.filter((p) => {
                    return p.name.indexOf(this.keyWord) !== -1
                })
            }
        }
    })
</script>
</body>
</html>

列表排序

先过滤在排序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
    <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.age}} - {{p.sex}}
        </li>
    </ul>
</div>
<script>
    Vue.config.productionTip = false
    const vm = new Vue({
        el: "#app",
        data: {
            keyWord: "",
            sortType: 0,// 0原顺序  1降序 2升序
            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: {
            filpersons() {
                const arr = this.persons.filter((p) => {
                    return p.name.indexOf(this.keyWord) !== -1
                })
                if (this.sortType) {
                    arr.sort((a, b) => {
                        return this.sortType === 1 ? b.age - a.age : a.age - b.age
                    })
                }
                return arr
            }
        }
    })
</script>
</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿瞒有我良计15

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值