【学习前端第六十五课】vue框架中的key详解

文章讲述了在Vue中使用key的注意事项,特别是在动态渲染时,为何不应使用索引作为key,以及如何通过使用`item.sid`作为key来解决状态管理和性能问题。还提供了一个示例演示了如何在列表过渡动画中正确应用key。
摘要由CSDN通过智能技术生成

vue框架中的key详解

之前我们在左列表渲染的时候,包括现在我们做的过渡动画,我们都看到了一个key,之前给大家讲key的时候说过key的值不能重复,所以我们一直在做索引作为key的值

不推荐使用index的值作为key的值

如果执行的时静态渲染,则使用index作为key其实也还好,但是如果执行的是动态渲染,则index千万不能作为key的值使用,否则vue内部的状态机制容易出错

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(item,inde) in stuList" :key="index">
                学号:{{item.sid}} ------ 姓名:{{item.sname}}
            </li>
        </ul>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data:{
            stuList:[
                {sid:"001",sname:"zhangsan"},
                {sid:"002",sname:"lisi"},
                {sid:"003",sname:"wangwu"}
            ]
        }
    })
</script>
</html>

这就是一个静态渲染,因为stuList数组在后面的操作种不会发生变化

存在的问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        学号:<input type="text" v-model="sid">
        姓名:<input type="text" v-model="sname">
        <button type="button" @click="addData">添加</button>
        <ul>
            <li v-for="(item,inde) in stuList" :key="index">
                <input type="checkbox" >
                学号:{{item.sid}} ------ 姓名:{{item.sname}}
            </li>
        </ul>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data:{
            sid:"",
            sname:"",
            stuList:[
                {sid:"001",sname:"zhangsan"},
                {sid:"002",sname:"lisi"},
                {sid:"003",sname:"wangwu"}
            ]
        },
        methods:{
            addData(){
                this.stuList.unshift({
                    sid:this.sid,
                    sname:this.sname
                });
                this.sid = "";
                this.sname = "";
            }
        }
    })
</script>
</html>

这个时候我们会发现我们在没添加数据之前,勾选的是lisi,但是在添加数据之后勾选却变成了zhangsan

原因:

在vue的内部,vue使用key来控制状态,而我们渲染的时候不是通过key记录的状态来渲染的

<li v-for="(item,index) in stuList" :key="index">
    <input type="checkbox" >
    学号:{{item.sid}} ------ 姓名:{{item.sname}}
</li>

我们的内部状态使用索引作为key,所以在变化之前,vue记住key为1的这一项是勾选的,然后下次再重新渲染的时候,vue记住的状态是索引值1,所以渲染出来的结果也就是勾选的key值为1的哪一项,但是实际渲染index对应的数据已经改变了

vue在执行内部渲染的时候,执行是一个叫做diff算法,它把渲染之前和渲染之后的数据进行比较,然后只更新差异项

vue内部在执行渲染之前的数据与渲染之后做比较,这个时候对比的是key

它在执行对比的时候,发现每个key都改变了,它就又重新渲染了4个,但是本来应该就渲染1个就够了,也就是说上面的代码极大的消耗了浏览器性能,所以如果要执行的是动态渲染,我们不推荐使用index作为key

解决方案

<li v-for="(item,index) in stuList" :key="item.sid">
    <input type="checkbox" >
    学号:{{item.sid}} ------ 姓名:{{item.sname}}
</li>
案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .list-box{
            list-style:none;
            margin:0;
            padding:0;
            display: flex;
        }
        .list-box>li{
            width:40px;
            height:40px;
            background:red;
            margin:5px;
            display:flex;
            justify-content: center;
            align-items: center;
            color:#fff;
        }
        .aaa-enter{
            transform: translateY(-150%);
            opacity: 0;
        }
        .aaa-enter-to,.aaa-leave{
            transform: translateY(0);
            opacity: 1;
        }
        .aaa-leave-to{
            transform: translateY(150%);
            opacity: 0;
        }
        .aaa-enter-active,.aaa-leave-active{
            transition: all .5s linear;
        }
    </style>
</head>
<body>
    <div id="app">
        <button type="button" @click="add">+</button>
        <button type="button" @click="sub">-</button>
        <transition-group tag="ul" class="list-box" name="aaa">
            <li v-for="(item,index) in numList" :key="item+'aaa'">{{item}}</li>
        </transition-group>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    new Vue({
        el:"#app",
        data:{
            numList:[0,1,2,3]
        },
        methods:{
            add(){
                this.numList.push(this.numList.length);
            },
            sub(){
                let index = parseInt(Math.random() * this.numList.length);
                this.numList.splice(index,1);
            }
        }
    })
</script>
</html>
  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值