• 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()的使用

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

    1. <body>
    2. <div id="root">
    3. <h2>学校:{{name}}h2>
    4. <h2>地址:{{address}}h2>
    5. <h2>学生姓名:{{student.studentName}}h2>
    6. <h2>学生年龄:{{student.studentAge}}h2>
    7. div>
    8. <script src="./js/vue.js">script>
    9. <script>
    10. Vue.config.productionTip = false
    11. const vm = new Vue({
    12. el:'#root',
    13. data:{
    14. name:'尚硅谷',
    15. address:'北京',
    16. student:{
    17. studentName:'tom',
    18. // studentAge:18
    19. }
    20. }
    21. })
    22. script>
    23. 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~

    1. <body>
    2. <div id="root">
    3. <h2>学校:{{name}}h2>
    4. <h2>地址:{{address}}h2>
    5. <h2>学生姓名:{{student.studentName}}h2>
    6. <button @click="addAge">点击添加年龄button>
    7. <h2 v-if="student.studentAge">学生年龄:{{student.studentAge}}h2>
    8. div>
    9. <script src="./js/vue.js">script>
    10. <script>
    11. Vue.config.productionTip = false
    12. const vm = new Vue({
    13. el:'#root',
    14. data:{
    15. name:'尚硅谷',
    16. address:'北京',
    17. student:{
    18. studentName:'tom',
    19. // studentAge:18
    20. }
    21. },
    22. methods: {
    23. addAge(){
    24. Vue.set(this.student,'studentAge',19)
    25. }
    26. },
    27. })
    28. script>
    29. body>

    效果图:

    拜比~ 

  • 相关阅读:
    一款适用于.Net的高性能文件上传项目
    UE4 命名规范
    H5 鼠标点击粒子扩散效果
    react-router-dom
    什么是会话固定以及如何在 Node.js 中防止它
    java-php-python-基于的高速公路服务区管理系统计算机毕业设计
    Kubernetes客户端认证(二)—— 基于ServiceAccount的JWTToken认证
    JVM的故事——类文件结构
    过滤表filter达式cql相互转化
    springboot + mysql的dorker部署
  • 原文地址:https://blog.csdn.net/m0_72383454/article/details/127024677