(十三)Vue之监测数据改变的原理

news2024/11/28 8:42:31

文章目录

  • 监测数据改变的原理之对象
    • vue.set的使用
  • 监测数据改变的原理之数组

Vue学习目录

上一篇:(十二)Vue之列表渲染

先看一个需求:使用列表渲染出一组数据,然后点击按钮更新其中一个信息
在这里插入图片描述

<!--准备好一个容器-->
    <div id="root">
        <!--第一步:收集用户输入的数据-->
        <button @click="updateMei">更新马冬梅的信息</button>
        <ul>
            <li v-for="(person,index) in persons" :key="person.id">{{person.name}}-{{person.age}}-{{person.sex}}</li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示。
        //第二步:使用监视属性或者计算属性进行过滤
        const vm = new Vue({
            el:'#root',
            data:{
                persons:[
                    {id:'001',name:'马冬梅',age:22,sex:'女'},
                    {id:'002',name:'周冬雨',age:19,sex:'女'},
                    {id:'003',name:'周杰伦',age:21,sex:'男'},
                    {id:'004',name:'温兆伦',age:20,sex:'男'}
                ]
            },
            methods:{
                updateMei(){
                    this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'}
                }
            }
        });
    </script>

效果:无论怎么点按钮,数据都不会改变,打开Vue开发者工具,发现数据改变了,但是页面没有改变,不奏效,vue没有承认你这次修改。
请添加图片描述
请添加图片描述
如果把更新的逻辑改成如下:

       updateMei(){
           this.persons[0].name = '马老师'
           this.persons[0].age = 50
           this.persons[0].sex = '男'           
       }

效果:点击按钮,页面数据改变,Vue开发者工具也改变
请添加图片描述
请添加图片描述

监测数据改变的原理之对象

之前说过vm里面的_data存储了data数据,但可不是直接存储,vue会对data里面的数据做一些加工,我们打开发现里面有setter、getter,之前说过不是数据代理,而是数据劫持,你只要一改data数据,setter就会被调用,而且这个setter是一个响应式的setter,响应式的setter就是这个setter里面调了一个方法,这个方法会引起模板的解析。
我们把这种一旦修改data里的数据,就会被setter拦截到,或者获取数据时,会被getter拦截到,叫做数据劫持
那是怎么实现的呢,我们可以模拟一个数据监测。
数据监测步骤:数据监测也是通过Object.defineProperty进行实现的

  • 1.创建一个监视的实例对象,用于监视数据中属性的变化
  • 2.汇总对象中所有的属性形成一个数组
  • 3.遍历,为其添加getter和setter
  • 4.准备一个实例对象,把数据和监视对象赋给它
<script type="text/javascript">
        let data = {
            name:'一中',
            addr:'广州', 
        }
        //1.创建一个监视的实例对象,用于监视data中属性的变化
        const obs = new Observer(data)

        //4.准备一个vm实例对象
        let vm = {}
        vm._data = data = obs

        function Observer(obj){
            //2.汇总对象中所有的属性形成一个数组
            const keys = Object.keys(obj)
            //3.遍历
            keys.forEach((k)=>{
                Object.defineProperty(this,k,{
                    get(){
                        console.log('get被调用')
                        return obj[k]
                    },
                    set(val){
                        console.log(`${k}被改了,去解析模板,生成虚拟DOM.....`)
                        obj[k] = val
                    }
                })
            })
        }
    </script>

效果:不管访问/修改data的数据,还是访问/修改vm里_data的数据,都能监测得到。
在这里插入图片描述
当然我们模拟的监测也是有局限性的,如果写了一个对象,我们当前程序就废了,因为我们只考虑了一层,vue是用递归实现,它会一直往下找,直到找到不是对象为止。vue做得更好的是哪怕是一个数组对象,也能找到最低层。

vue.set的使用

我们想在data外面给data里面的对象添加属性,如果直接进行添加的话,是没有setter和getter,也就是说,vue不会对这个属性进行监测,只是当作普通的一个属性,也没有响应式,在页面不会进行展示。
在vue可以使用vue.set进行添加属性:
Vue里的set,会自动添加setter和getter,function set (target, key, val);
三个参数:

  • target:要添加的对象
  • key:添加的属性名
  • val:添加的属性值

vm上与Vue里的set一样效果
vm.$set()
注意:Vue.set()vm.\$set() 不能给vm 或 vm的根数据对象 添加属性!!!

<div id="root">
        <h1>学校信息</h1>
        <h2>学校名称:{{name}}</h2>
        <h2>学校名称:{{addr}}</h2>
        <h1>学生信息</h1>
        <button @click="addSex">添加性别,默认是男</button>
        <h2>学生姓名:{{student.name}}</h2>
        <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
        <h2>学生年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
        <h2>朋友们</h2>
        <ul>
            <li v-for="(friend,index) in student.friends" :key="index">
                {{friend.name}}--{{friend.age}}
            </li>
        </ul>
    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示。
        const vm = new Vue({
            el:'#root',
            data:{
                name:'一中',
                addr:'广州',
                student:{
                    name:'tom',
                    age:{
                        rAge:40,//真实年龄
                        sAge:29,//对外年龄
                    },
                    friends:[
                        {name:'jack',age:35},
                        {name:'tony',age:34}
                    ]
                }
            },
            methods:{
                addSex(){
                    //直接添加没有响应式
                    //this.student.sex = '男'
                    
                    //Vue.set
                    //Vue.set(this.student,'sex','男')
                    //vm.$set()
                    this.$set(this.student,'sex','男')
                }
            }
        });

效果:点击按钮,添加了属性,在vm身上也有setter和getter进行页面的响应

请添加图片描述
在这里插入图片描述

监测数据改变的原理之数组

上面程序基础上添加一个爱好属性,并进行展示

		<h2>爱好</h2>
        <ul>
            <li v-for="(h,index) in student.hobby" :key="index">
                {{h}}
            </li>
        </ul>
		data:{
                name:'一中',
                addr:'广州',
                student:{
                    name:'tom',
                    age:{
                        rAge:40,//真实年龄
                        sAge:29,//对外年龄
                    },
                    hobby:['抽烟','喝酒','烫头'],
                    friends:[
                        {name:'jack',age:35},
                        {name:'tony',age:34}
                    ]
                }
            },

效果:
在这里插入图片描述
去控制台查看vm中的hobby和根friends,发现没有setter和getter,而且通过最上面的程序我们知道直接改数组的数据,不会导致页面的更新。
在这里插入图片描述
那vue是怎么对数组做监测的呢?
vue是通过这些API得知数组的变更:

push()pop()shift()unshift()splice()sort()reverse()

一旦对数组使用了上面的API,vue就会做响应式处理。
那vue怎么得知你使用上面这些API呢?
vue是对这些API进行了包装(装饰器模式),形成了自己的API,如果你通过数组调用这些方法,实际上是调用vue自己写的API。

我们查看hobby和根friends的Prototype,发现了vue对这些API进行了包装
请添加图片描述

vue对这些方法做了两件事:

  • 1.调用数组原型对象对应的方法。
  • 2.进行页面的响应。

数组中的某个元素还可以使用Vue.set()或vm.$set(),也会导致页面数据更新。

注意:filter()、concat() 和 slice()等等。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/85568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微服务中统一日志-ELK

微服务中统一日志-ELK一.简介1.介绍2.流程3.要求4.下载地址二.安装Elasticsearch1.创建文件存放目录2.进入目录3.下载4.解压5.修改配置5.1.介绍5.2.系统配置5.3修改es配置5.4启动&#xff0c;测试三.安装Kibana1.进入目录2.下载3.解压4.修改配置4.1介绍4.2修改kibana配置4.3启动…

面试八股-JVM

1.Java代码编译过程 准备过程&#xff1a;初始化插入式注解处理器解析与填充符号表过程 词法、语法分析&#xff0c;将字符流转为标记集合&#xff0c;构造抽象语法树填充符号表&#xff0c;产生符号地址和符号信息 插入式注解处理器的注解处理分析与字节码生成过程 标注检查&…

描述统计 | 学习笔记

一.导论 统计学是通过收集&#xff0c;整理&#xff0c;分析&#xff0c;描述数据等手段&#xff0c;以达到推断所测对象的本质&#xff0c;甚至预测对象未来的一门综合性科学。其目的是探索数据的内在数量规律性&#xff0c;以达到对客观事物的科学认识 统计的本业是消化数据…

java语言【#107. 七的奇倍数】(已通过)

题目描述 ​ 如果一个数既是 7 的倍数又不能被 2 整除&#xff0c;那么我们称之为七的奇倍数。 ​ 输入一个正整数 n&#xff0c;判断它是否是 7 的奇倍数。 输入 ​ 输入一个正整数 n &#xff08;0≤n≤100&#xff09; 输出 ​ 如果 n 是 7 的奇倍数 输出 YES 否则输出 NO…

校园二手市场开题报告范文

目录 一、课题意义&#xff08;包括课题的理论意义和现实意义&#xff09; &#xff08;一&#xff09;理论意义 &#xff08;二&#xff09;现实意义 二、文献综述&#xff08;包括&#xff1a;1.理论的渊源及演进过程2.国内外对本课题的研究现状和有待解决的问题3.本人对所…

适合rv1109+rv1126使用基于RKmedia的人脸和车牌识别的SDK及使用介绍说明

基于RKmedia开发的人脸识别和车牌识别SDK简介及使用 一、功能简介 SDK下载&#xff1a;https://download.csdn.net/download/DeepLearning_/87272848 人脸检测&识别 对于人脸部分&#xff0c;SDK 提供了以下能力&#xff1a; 1. 人脸检测 1.1 人脸是否带口罩判定 1.2…

路由器的安装方法步骤

路由器的安装和设置如下&#xff1a; 1.首先连接线路&#xff0c;可以参考下图 2.线路连接完毕后&#xff0c;打开浏览器输入路由器的管理地址和管理密码然后进入路由器后台&#xff08;具体路由器的登录地址和登录密码可以参考说明书或者是路由器背面的标签&#xff09; 3.…

Nacos配置管理-配置热更新

Nacos配置自动刷新 Nacos中的配置文件变更后&#xff0c;微服务无需重启就可以感知。不过需要通过下面两种配置实现&#xff1a; 热更新-方法一&#xff1a;使用RefreshScope注解 在Value注入的变量所在类上添加RefreshScope注解&#xff1b; RestController RequestMapping(&…

直播|BIA Separations 和元生物两位大咖关于质粒DNA的制造工艺和质量控制

质粒 DNA&#xff08;pDNA&#xff09; 是生物研究和治疗开发中用于转移或表达基因的一个基本组成部分。细胞与基因治疗中最常用的载体AAV和慢病毒的生产都需要质粒作为起始材料&#xff0c;随着基因治疗&#xff0c;细胞治疗及DNA疫苗的快速发展&#xff0c;快速高效的大规模工…

腾讯云原生数据湖存储服务能力再上新,三级加速体系助力企业用数赋智

随着数据价值被越来越多企业认可&#xff0c;数据湖存储已成为企业级存储的首选和新一代提升生产力的服务。12月1日&#xff0c;在2022腾讯数字生态大会存储专场&#xff0c;腾讯云升级了云原生数据湖产品能力&#xff0c;并详细阐释了其设计理念&#xff0c;对其在多个行业的应…

数据万象技术演进之路

前言 Dale&#xff08;1969&#xff09;的“经验之塔”指出人们获取信息70%以上是通过视觉途径&#xff0c;在互联网时代也不例外。在当今图片音视频服务等已成为一个互联网应用中占比很大的部分&#xff0c;对图片和音视频等数据的处理能力也相应变成企业和开发者的一项基本技…

C++中二叉树的非递归遍历方法2-2

4 代码实现二叉树的非递归遍历 在“2 二叉树的遍历方法”中提到&#xff0c;二叉树的遍历方法有前序遍历、中序遍历、后序遍历属于深度优先遍历。接下来以前序遍历为例&#xff0c;通过代码实现该方法的二叉树非递归遍历。 4.1 前序遍历 4.1.1 前序遍历的非递归步骤 因为前…

记一次go协程读写锁 sync.RWMutex未释放导致其他协程阻塞bug

记一次go协程读写锁 sync.RWMutex未释放导致其他协程阻塞bug记一次go协程读写锁 sync.RWMutex未释放导致其他协程阻塞bug用到的监测工具程序简要介绍示例代码运行结果运行结果分析记一次go协程读写锁 sync.RWMutex未释放导致其他协程阻塞bug 通过一个简单示例模拟某协程结束&a…

[附源码]Python计算机毕业设计电影院订票系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

第53篇 Qt Quick项目详解

导语 前面我们一起创建了一个Qt Quick项目&#xff0c;并对里面的文件进行了简单的讲解&#xff0c;虽然这只是一个HelloWorld程序&#xff0c;但对于没有Qt Quick编程经验的同学来说&#xff0c;这个项目还是有点复杂。在这一篇中&#xff0c;我们将从最简单的QML文件讲起&am…

Flutter Web CORS解决方案1-禁用浏览器安全策略

Flutter Web CORS解决方案1设置CHROME_EXECUTABLE关于 CHROME_EXECUTABLE创建 CHROME_EXECUTABLE修改 chrome.dart 禁用安全策略升级 flutterSDK 后需重新修改升级后指定--web-hostname参数问题浏览器启用 Allow-CORS 插件部分协议OPTIONS预检跨域问题本文介绍第一种解决Flutte…

《纳瓦尔宝典》笔记一——你是在跟自己竞争,这是一场单人游戏

目录 一、身体的健康是top1 二、你唯一拥有的就是时间 三、选择短期内更更痛苦的道路 四、人生早期有三个重大决定 五、从雇佣关系中解脱出来 六、找合作伙伴 七、你真的嫉妒别人吗 八、从期待中解放出来 九、向内求-内在的评价标准 十、人生的大赢家就是同时拥有时间…

[附源码]Nodejs计算机毕业设计基于RationalRose的教务管理系统开发Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

基于java+swing+mysql图书管理系统3

大作业-基于java swing图书管理系统3一、系统介绍二、功能展示1.管理员登陆2.图书类别添加3.图书类别维护4.图书添加5.图书维护三、系统实现1.BookManageMainFrame.java四、其它1.其他系统实现五.获取源码一、系统介绍 该系统实现了用户登陆、图书类别管理(图书类别添加、图书…

JavaEE 初始化两个上下文对象,导致更新网站访问次数更新失败

问题描述 &#xff1a; 在做网站次数统计的时候&#xff0c;需要用到上下文对象&#xff0c;最终在上下文监听中发现上下文对象创建两次&#xff0c;销毁两次&#xff0c;导致数据库中网站访问次数统计更新失败。 原因 &#xff1a; 我们更改了项目的访问路径&#xff0c;就会导…