Vue2(四):Vue监测数据的原理(对象,数组),Vue.set的使用方法

一、更新时的一个问题

如果我要点击按钮实现更新冯万宁儿的信息,那么如果一个属性一个属性地改,可以修改成功,并且Vue也会检测到并更新到页面。

但是我如果直接把要修改的信息写在this.persons[0] = { id: 001, name: '冯千宁儿', age: 66, sex: '女' };这里,就不行,Vue监测不到并且不更新到页面,这是为什么?

    <!-- 准备好一个容器 --><div id="root"><h1>人员列表</h1><button @click="updateNing">点击更新冯万宁儿</button><ul><li v-for="(p,index) in persons" :key="p.id">{{p.name}}----{{p.age}}----{{p.sex}}</li></ul></div><script>const vm = new Vue({el: '#root',data: {keyword: '',persons: [{ id: 001, name: '冯万宁儿', age: 23, sex: '男' },{ id: 002, name: '屁及万儿', age: 18, sex: '男' },{ id: 003, name: '及丽热巴', age: 10, sex: '女' },{ id: 004, name: '冯小刚儿', age: 60, sex: '男' }]},methods: {updateNing() {// this.persons[0].name = '冯千宁儿';     //奏效// this.persons[0].age = 66;        //奏效// this.persons[0].sex = '女';      //奏效this.persons[0] = { id: 001, name: '冯千宁儿', age: 66, sex: '女' };//上面这么写,也奏效,数据实际上已经改了,但是Vue监测不到所以没更新到页面,为啥捏?}}})</script>

二、原生js模拟Vue监视data对象中的数据

用原生js写一个Vue监视data数据改变的效果

可以看出,Vue监视数据的原理,就是靠setter

<script type="text/javascript">let data = {name : 'cgp',age : 18}// 创建一个监视的实例对象,用于监视data中属性的变化const obs = new Observer(data)console.log(obs);// 准备一个vm实例对象let vm = {}vm._data = data = obsfunction Observer(obj){// 汇总对象中所有的属性形成一个数组const keys = Object.keys(obj)// 遍历keys.forEach((k)=>{Object.defineProperty(this,k,{get(){return obj[k]},set(val){console.log('${k}被改了,我要去解析模板,生成虚拟dom....');obj[k]=val}})})}</script>

这只是个模拟,实际上Vue做了更多事情,比如:
1、在setter中不是简单的输出,而是重新解析模板,生成虚拟DOM,新旧虚拟DOM对比,更新页面实现响应式。
2、Vue中vm还对_data做了数据代理,我可以直接vm.name,不用vm._data.name
3、我这么写,如果数据是套娃的(对象中还有对象还有对象),就监测不到。但是Vue就可以,不管你数据藏得多深,Vue都能找到,每个数据都有自己的getter和setter。只要有数据被改,就会实现响应式。(这里面好像涉及了深拷贝的知识?

三、Vue监测对象中的数据

 1、监视对象中的数据

1、vue会监视data中所有层次的数据,不管你藏得有多深。
2、如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理
(2).如需给后添加的属性做响应式,请使用如下API:

Vue.set(target,propertyName/index,value) 或 
vm.$set(target,propertyName/index,value)

2、Vue.set的使用

用法:

向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi')

注意对象不能是 Vue 实例,或者 Vue 实例的根数据对象。

_data在收集data中的数据之前,先做了一个加工(这个加工也可以称之为数据劫持),那就是给每个数据匹配一个getter和setter,前面说了,Vue监视数据的原理,就是靠setter。所以如果我们后期手动直接给_data添加属性(注意区别手动添加和从data中收集),是无法实现响应式的,因为没办法给它setter,只有从data中收集过来的属性才能通过一个鱿鱼西定义的好像是叫Observer什么什么的方法给它搞个setter。

Vue.set()是有局限性的!!!它只能给data中的某个对象追加属性,不能给vm 或 vm的根数据对象(data或_data) 添加属性!!!
也就是说第一个参数不能是 Vue 实例,或者 Vue 实例的根数据对象(_data)

例如给学生添加性别:

    <div id="root"><h1>学校信息</h1><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><hr><h1>学生信息</h1><button @click="add">添加性别</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="(f,index) in student.friends" :key="index">{{f.name}}----{{f.age}}</li></ul></div><script>const vm = new Vue({el:'#root',data:{name:'椰果',address:'郑州',student:{name:'cgp',age:{rAge:'18',sAge:'19'},friends:[{name:'yhg',age:'20'},{name:'zym',age:'21'}]}},methods:{add(){// Vue.set(this.student,'sex','男')this.$set(this.student,'sex','男')}}})</script>

四、Vue监测数组中的数据 

1.如何监测数组中的数据?


其实是Vue里面定义了一个非常牛逼的方法,目的只有一个:实现响应式。

方法里包装的代码本质就是做了两件事:
(1)调用原生对应的方法对数组进行更新。然后第二步在这个基础上再加点料
(2)重新解析模板,生成虚拟DOM,diff算法……进而更新页面,实现响应式。

所以在Vue修改数组中的某个元素实现响应式一定要用如下方法:
(1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
(2)Vue.set() 或 vm.$set()也可以实现响应式,第二个参数写索引,第三个写元素,可以改也可以加

2、例如

<div id="root"><h2>我的名字:{{name}}</h2><h2>我的年龄:{{age}}</h2><hr><h2>他的名字:{{boyfriend.name}}</h2><button @click="addHobby">点击替换'跳'的爱好</button><h2>爱好</h2><ul><li v-for="(h,index) in girlfriend.hobby" :key="index">{{h}}</li></ul>
</div>
<script>const vm = new Vue({el: '#root',data: {name: 'cgp',age: 18,girlfriend: {name: 'ht',hobby: ['唱', '跳', 'rap']}},methods: {addHobby() {//除了那7个方法外,set方法也可以改变数组实现响应式Vue.set(this.girlfriend.hobby, 1, '打游戏');}},})  
</script>

五、回头看看第一个问题

说了这么多,再回头看第一个问题,就恍然大悟了
1、单独改每个属性可以奏效,是因为Vue可以监测到对象里的每个属性,不管它藏的多深,只要是个对象,就有相应的getter和setter
2、将数组中的元素单独替换,数据修改成功,但是Vue没有监测到,页面不显示,这是因为数组中的每个元素是没有getter和setter的,如果修改数组中的元素无法实现响应式.
3、要想让更改数组中的元素实现响应式,就得调用数组的七个api或者用Vue.set()方法

<!-- 准备好一个容器 -->
<div id="root"><h1>人员列表</h1><button @click="updateNing">更新冯万宁儿</button><ul><li v-for="(p,index) in persons" :key="p.id">{{p.name}}----{{p.age}}----{{p.sex}}</li></ul>
</div><script>const vm = new Vue({el: '#root',data: {persons: [{ id: 001, name: '冯万宁儿', age: 23, sex: '男' },{ id: 002, name: '屁及万儿', age: 18, sex: '男' },{ id: 003, name: '及丽热巴', age: 10, sex: '女' },{ id: 004, name: '冯小刚儿', age: 60, sex: '男' }],},methods: {updateNing() {// this.persons[0].name = '冯千宁儿';     //奏效// this.persons[0].age = 66;        //奏效// this.persons[0].sex = '女';      //奏效// this.persons[0] = { id: 001, name: '冯千宁儿', age: 66, sex: '女' };//上面这么写,也奏效,数据实际上已经改了,但是Vue监测不到所以没更新到页面,为啥捏?//实际上是因为Vue监测数组时,数组没有相应的setter和getter,直接改Vue监测不到//但是数组中的每个对象中的属性都有自己的getter,setter,所以单独改属性时可以监测到的//要想让更改数组中的元素实现响应式,就得调用数组的七个api或者用setthis.persons.splice(0, 1, { id: 001, name: '冯千宁儿', age: 66, sex: '女' });}}})
</script>

六、练习 

<div id="root"><button @click="addSex">添加一个性别属性,默认为女</button><button @click="addHeight">添加一个身高属性,默认为170</button><br><button @click="girlfriend.age.realAge--">年龄-1</button><button @click="addFriend">在列表前加一个朋友</button><br><button @click="updateFriend">修改第一个朋友的名字为张三</button><button @click="addHobby">添加一个爱好</button><br><button @click="updateHobby">修改第一个爱好为散步</button><button @click="removeHobby">过滤掉爱好中的跳</button><h2>名字:{{girlfriend.name}}</h2><h2>年龄:对外{{girlfriend.age.fakeAge}},真实{{girlfriend.age.realAge}}</h2><h2 v-if="girlfriend.sex">性别:{{girlfriend.sex}}</h2><h2 v-if="girlfriend.height">身高:{{girlfriend.height}}</h2><h2>朋友们</h2><ul><li v-for="p in girlfriend.friends" :key="p.id">{{p.name}}----{{p.age}}</li></ul><h2>爱好</h2><ul><li v-for="(h,index) in girlfriend.hobby" :key="index">{{h}}</li></ul>
</div>
<script>const vm = new Vue({el: '#root',data: {name: 'zzy',age: 18,girlfriend: {name: 'ht',// sex: '女',age: {realAge: 23,fakeAge: 18},friends: [{ id: 001, name: 'jack', age: 10 },{ id: 002, name: 'rose', age: 8 },],hobby: ['唱', '跳', 'rap']}},methods: {addSex() {Vue.set(this.girlfriend, 'sex', '女');},addHeight() {this.$set(this.girlfriend, 'height', 170);},addFriend() {this.girlfriend.friends.unshift({ id: 003, name: 'alice', age: 5 });  //有效写法},updateFriend() {this.girlfriend.friends[0].name = '张三';},addHobby() {this.girlfriend.hobby.push('打游戏');},updateHobby() {// this.girlfriend.hobby[0] = '散步';  //无效写法// this.girlfriend.hobby.splice(0, 1, '散步');   //有效写法Vue.set(this.girlfriend.hobby, 0, '散步');   //有效写法},removeHobby() {// 变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法// 例如 filter()、concat() 和 slice()。它们不会变更原始数组,而总是返回一个新数组。// 当使用非变更方法时,可以用新数组替换旧数组:this.girlfriend.hobby = this.girlfriend.hobby.filter((ele) => {return ele !== '跳';})}},})
</script>

(ps:今天一个好消息补考过了!听懂了 也要再练习一下哦)

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

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

相关文章

Android Studio中快速修改包名

Android Studio中快速修改包名 假设原包名是com.abc.efg&#xff0c; 新包名是com.aaa.bbb 1、点击齿轮图标&#xff0c;把Compact Middle Packages前面的对勾取消&#xff0c;如果没有就忽略此步 2、在左侧项目栏中&#xff0c;选择Android, App-->java-->com,下面可以看…

SpringBoot程序的核心功能及优点

本篇博客主要记录SpringBoot程序的核心功能及优点&#xff1a; 起步依赖&#xff08;简化依赖配置&#xff09; 依赖配置的书写简化就是靠这个起步依赖达成的。 自动配置&#xff08;简化常用工程相关配置&#xff09; 配置过于繁琐&#xff0c;使用自动配置就可以做相应的简化…

教程:如何制作和分享自定义GPT

自定义GPT教程&#xff1a;如何制作和分享 引言 人工智能领域不断发展&#xff0c;引入了改变我们与科技互动方式的创新工具。在这些创新中&#xff0c;自定义生成式预训练变压器&#xff08;GPT&#xff09;的出现尤为引人注目。这些AI模型超越了标准ChatGPT的功能&#xff…

YOLOv9算法原理——使用可编程梯度信息学习想要学习的内容

前言 2023年1月发布YOLOv8正式版后&#xff0c;经过一年多的等待&#xff0c;YOLOv9终于面世了&#xff01;YOLO是一种利用图像全局信息进行目标检测的系统。自从2015年Joseph Redmon、Ali Farhadi等人提出了第一代模型以来&#xff0c;该领域的研究者们已经对YOLO进行了多次更…

k8s HPA 自动伸缩机制 (配置,资源限制,)

目录 一、概念 核心概念 工作原理 HPA 的配置关键参数 关键组件 使用场景 注意事项 如何确保程序稳定和服务连续 二、metrics-server 部署 metrics-server 准备 metrics-server 镜像: 使用 Helm 安装 metrics-server: 配置 metrics-server: 安装 metrics-server: …

EOS 与ESD 区别

ESD: 英文&#xff1a;Electrical Static Discharge&#xff1b; 定义&#xff1a;不同静电电位的两个物体之间的电荷转移&#xff1b;中文释为静电放电。静电是一种客观的自然现象&#xff1b; EOS&#xff1a; 英文&#xff1a;Electrical Over Stress 定义&#xf…

【算法】KY187 二进制数

https://www.nowcoder.com/ta/kaoyan 描述 大家都知道&#xff0c;数据在计算机里中存储是以二进制的形式存储的。 有一天&#xff0c;小明学了C语言之后&#xff0c;他想知道一个类型为unsigned int 类型的数字&#xff0c;存储在计算机中的二进制串是什么样子的。 你能帮帮小…

C++中在定义一个宏的时候要注意什么?

在定义宏时&#xff0c;有一些重要的注意事项需要牢记&#xff0c;以确保代码的正确性、可读性和可维护性。以下是一些关键的建议&#xff1a; 避免副作用&#xff1a;宏只是简单的文本替换&#xff0c;所以它们不会检查是否有变量被多次修改或者是否有潜在的副作用。例如&…

钉钉小程序 - - - - - 如何通过一个链接打开小程序内的指定页面

方式1 钉钉小程序 scheme dingtalk://dingtalkclient/action/open_mini_app?miniAppId123&pagepages%2Findex%2Findex%3Fx%3D%25E4%25B8%25AD%25E6%2596%2587 方式2 https://applink.dingtalk.com/action/open_mini_app?type2&miniAppIdminiAppId&corpIdcorpId&…

spacy进行简单的自然语言处理的学习

自然语言处理基本概念 概念&#xff1a;自然语言处理&#xff0c;是让机器理解人的语言的过程。 作用&#xff1a;通过使用自然语言处理&#xff0c;机器可以理解人的语言&#xff0c;从而进行语义分析&#xff0c;例如&#xff1a;从一句话中判断喜怒哀乐&#xff1b;从一段文…

计算机安全

一、跨站脚本攻击XSS? XSS就是通过在用户端注入恶意的可运行脚本&#xff0c;若服务端对用户的输入不进行处理&#xff0c;直接将用户的输入输出到浏览器&#xff0c;然后浏览器将会执行用户注入的脚本。 获取用户的输入&#xff0c;不用innerHtml,用innerText; 对用户的输入…

Unity类银河恶魔城学习记录10-12 p100 Improve aliments - chill源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili CharacterStats.cs using System.Collections; using System.Collections…

【每日算法】理论:生成模型基础; 刷题:力扣单调栈

文章目录 一、理论问题1、怎么理解重参数化技术&#xff1f;2、KL散度是什么&#xff1f;3、DDPM4、什么是马尔可夫过程5、GAN模型6、VAE模型 二、力扣回顾-单调栈 一、理论问题 1、怎么理解重参数化技术&#xff1f; 重参数化是神经网络中的一种技术&#xff0c;也可以称之为…

计算机二级Python题目13

目录 1. 基本题 1.1 基本题1 1.2 基本题2 1.3 基本题3 2. turtle画图 3. 大题 3.1 大题1 3.2 大题2 1. 基本题 1.1 基本题1 lseval(input()) s"" for item in ls:if type(item)type("香山"):s item print(s) 1.2 基本题2 import random random.se…

说下你对TCP以及TCP三次握手四次挥手的理解?

参考自简单理解TCP三次握手四次挥手 什么是TCP协议&#xff1f; TCP( Transmission control protocol )即传输控制协议&#xff0c;是一种面向连接、可靠的数据传输协议&#xff0c;它是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。 面向连接&a…

VMware的安装和Ubuntu的配置安装

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、linux是什么&#xff1f;二、基础知识虚拟机 三、安装VMware总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; Linux是一个功能…

Java项目:55 springboot基于SpringBoot的在线视频教育平台的设计与实现015

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 在线视频教育平台分为管理员和用户、教师三个角色的权限模块。 管理员所能使用的功能主要有&#xff1a;首页、个人中心、用户管理、教师管理、课程信…

数据指标体系方法—UJM模型

了解 UJM UJM 模型&#xff0c;全称为 User-Journey-Map 模型&#xff0c;即用户旅途地图。 UJM 模型是用户在使用产品过程中的生命旅程&#xff0c;指用户从首次接触直至下单以及享受产品或服务期间&#xff0c;用户与企业产品或者平台互动的全过程。 用户旅途常常会和用户…

用 bsdtar 做 Linux 全系统迁移 - 最省空间、最灵活的Linux系统迁移方式,但需要那么一点点技巧

&#xff08;首发地址&#xff1a;学习日记 https://www.learndiary.com/2024/03/migrate-linux-with-bsdtar/ &#xff09; 我们在做 Linux 全系统迁移的时候&#xff0c;可以直接备份磁盘或分区&#xff08;如 dd &#xff09;&#xff0c;也可以备份全部文件&#xff08;如…

想兼职赚钱?盘点6个靠谱兼职,赚钱更轻松!

1&#xff0c;微头条搬砖 微头条搬砖是一个门槛不高的赚钱方式&#xff0c;而且不需要你有多么好的原创能力&#xff0c;去收集一些热门文章的素材进行文章伪原创&#xff0c;十分钟就能搞定&#xff0c;只要你的文章有爆点&#xff0c;足够吸人眼球&#xff0c;就能够获取不低…