当前位置: 首页 > news >正文

VUE | key的内部原理、Vue监测数据的原理、Vue.set()和vm.$set()的使用

目录

目录

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

1.虚拟DOM中key的作用:

2.对比规则:

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

4.开发中如何选择key?

5.当index作为key时的原理图:

 6.当唯一标识(id)作为key时的原理图:

二、Vue监测数据的原理

三、Vue.set()的使用


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

1.虚拟DOM中key的作用:

key是虚拟DOM对象的标识,数据发生变化时,VUE会根据【新数据】生成【新的虚拟DOM】,随后VUE进行【新虚拟DOM】与【旧虚拟DOM】的差异比较。

2.对比规则:

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

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

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

4.开发中如何选择key?

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

5.当index作为key时的原理图:

 6.当唯一标识(id)作为key时的原理图:

二、Vue监测数据的原理

我们之前有在博客中说过,vm中的_data相当于复制了Vue在的data,所以实例对象中会有data中的所有属性,但仅仅是赋值嘛?

其实不是,在赋值之前会对data进行一个简单的加工,使data中的每一个属性都有自己的一个getter、setter。

当改变数据:调用setter --> 然后重新解析模板 --> 生成虚拟DOM --> 对比算法 --> 生成真实DOM  --> 重新渲染页面。

三、Vue.set()的使用

我们先来看一下这段代码:

<body>
    <div id="root">
        <h2>学校:{{name}}</h2>
        <h2>地址:{{address}}</h2>
        <h2>学生姓名:{{student.studentName}}</h2>
        <h2>学生年龄:{{student.studentAge}}</h2>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.config.productionTip = false

        const vm = new Vue({
            el:'#root',
            data:{
                name:'尚硅谷',
                address:'北京',
                student:{
                   studentName:'tom',
                //    studentAge:18
                }
            }
        })
    </script>
</body>

我们可以看到,我把【学生年龄】这个属性给注掉了,我们的模板还是有{{student.studentAge}}这个变量,可是并没有报错!是因为 【studentAge】并不是data中的属性。

接下来,我们想给它添加【studentAge】这个属性,在不直接操作data的情况下,我们应该怎么办呢?

有的同学可能会觉得,简单,直接【vm._data.student.studentAge = 18】不就可以了嘛!我们来试一下:

 可以看到,我们成功给_data添加了这个属性,但是页面并没有这个数据,这是为什么呢?

细心的同学可以看到,我们之前写的【studentName】或者其它之前就写好的属性都有自己的getter和setter,但是我们后面添加的这个属性却没有,没错!这就是导致我们页面没有办法更新数据的原因!!!

难道这就意味着,如果我们后期想要添加数据,就没有办法渲染到页面上了嘛?

当然不是啊,下面我们就来介绍一下Vue.set()这个方法。

Vue.set ( target , key , val )

  • target:给谁添加
  • key:添加什么属性
  • val:添加的属性值是多少

okk,我们现在就用这个办法来实现一下,我们刚刚的想法。

哈哈哈~是不是成功了,我们的【studentAge】也拥有了自己的getter和setter,真是皆大欢喜呐!

除了 Vue.set ( target , key , val )我们还可以通过 vm.$set(target , key , key )

好啦,我们就不在控制台操作了,给我们之前的代码做一个完善,就是我们今天的ending~

<body>
    <div id="root">
        <h2>学校:{{name}}</h2>
        <h2>地址:{{address}}</h2>
        <h2>学生姓名:{{student.studentName}}</h2>
        <button @click="addAge">点击添加年龄</button>
        <h2 v-if="student.studentAge">学生年龄:{{student.studentAge}}</h2>
        <!-- <h2>学生性别:{{student.sex}}</h2> -->
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.config.productionTip = false

        const vm = new Vue({
            el:'#root',
            data:{
                name:'尚硅谷',
                address:'北京',
                student:{
                   studentName:'tom',
                //    studentAge:18
                }
            },
            methods: {
                addAge(){
                    Vue.set(this.student,'studentAge',19)
                }
            },
        })
    </script>
</body>

效果图:

拜比~ 

相关文章:

  • Centos/Docker 环境中文乱码如何解决
  • VS2019 Qt源码编译
  • Linux8-fork父子进程逻辑地址相同、进程的逻辑地址与物理地址、fork相关例题、僵死进程
  • java毕业设计普通中学体育卫生信息管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  • 基于C语言的查找算法汇编
  • 多网段多通道IP地址和通讯端口转换
  • 【PyQt】PyQt入门安装和Hello World
  • 怎样创建一个VUE项目(超简单)
  • C++【STL】【queue的使用和模拟实现】【priority_queue的使用和模拟实现】
  • SAP PI PO 接口常见问题处理:在监控器中找不到一个或多个 XI 消息的日志记录
  • L2TP客户端之Strongswan移植(三)
  • matplotlib入门之抛砖引玉
  • java-php-python-springboot携手助学助学交流平台计算机毕业设计
  • Android wifi sniffer log总结分析
  • 山东大学数字图像处理实验(二)
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • Intervention/image 图片处理扩展包的安装和使用
  • JavaScript新鲜事·第5期
  • Python socket服务器端、客户端传送信息
  • Python学习笔记 字符串拼接
  • 阿里云购买磁盘后挂载
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 和 || 运算
  • 那些被忽略的 JavaScript 数组方法细节
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何编写一个可升级的智能合约
  • 实现菜单下拉伸展折叠效果demo
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • ​【C语言】长篇详解,字符系列篇3-----strstr,strtok,strerror字符串函数的使用【图文详解​】
  • ​力扣解法汇总946-验证栈序列
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (第一天)包装对象、作用域、创建对象
  • (二)换源+apt-get基础配置+搜狗拼音
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (三)mysql_MYSQL(三)
  • (转)fock函数详解
  • (转)LINQ之路
  • (转)菜鸟学数据库(三)——存储过程
  • ***测试-HTTP方法
  • .equals()到底是什么意思?
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .net core Swagger 过滤部分Api
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • ::什么意思
  • @Autowired自动装配
  • @DependsOn:解析 Spring 中的依赖关系之艺术
  • @GetMapping和@RequestMapping的区别
  • []sim300 GPRS数据收发程序
  • [2544]最短路 (两种算法)(HDU)
  • [Android]创建TabBar