读vue源码搞懂响应式原理

news2024/11/20 3:35:42

vue2响应式原理

  • Vue2是借助Object.defineProperty()实现的,而Vue3是借助Proxy实现的
  • 想深入学习 Vue2 的响应式原理, 需要先学习 Object.defineProperty() 方法
  • 为了称呼方便, 后续说 Vue 响应式原理统一指 Vue2 的响应式原理

1.Object.defineProperty 方法 - 简介

  • 定义一个对象 obj, 需要具备 name / age 等属性
  • age变化时, 在控制台打印最新的值
  • 当访问 obj.age 时, 控制台会显示 xxx 读取了 age 属性

演示

<!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="box">
    <p></p>
    <button id="btn">修改年龄</button>
  </div>
  <script>
    const obj = {
      name: 'zs'
    }

    Object.defineProperty(obj, 'age', {
      // 访问 obj.age 时这个方法会自动执行
      get() {
        console.log('有人访问了 age !', temp)
        return 18
      },
      // 给 obj.age 赋值时这个方法会自动执行, 我们也称之为拦截
      set(newVal) {
        console.log(newVal)
      } 
    })
    
    document.querySelector('p').innerHTML = `${ obj.name } --- ${ obj.age }`

    document.querySelector('#btn').onclick = function() {
      obj.age = 20
    }

  </script>
</body>
</html>

总结

  • 使用 Object.defineProperty() 可以无痕的监视到对象的属性什么时候发生变化, 什么时候被访问

2.Object.defineProperty 方法 - 利用临时变量来中转

  • 使用了 Object.defineProperty() 后发现 get / set 并不好用
  • 无法设置数据, 同时也不能获取到变化的属性

解决方法

  • 定义一个临时变量来中转

    <!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="box">
        <p></p>
        <button id="btn">修改年龄</button>
      </div>
      <script>
        const obj = {
          name: 'zs'
        }
    
        let temp = 18
    
        Object.defineProperty(obj, 'age', {
          // 访问 obj.age 时这个方法会自动执行
          get() {
            // 一般会在这里收集依赖, 例如: 网页中 p / h1 / div 等标签要渲染 age 数据
            // 注意: 这里是收集这些依赖, 下面会在 set 中自动通知这些依赖来更新 DOM
            console.log('有人访问了 age !', temp)
            return temp
          },
          // 给 obj.age 赋值时这个方法会自动执行, 我们也称之为拦截
          set(newVal) {
            // 一般当数据变更时, 通知依赖项更新 DOM
            console.log(newVal)
            temp = newVal
          } 
        })
        
        document.querySelector('p').innerHTML = `${ obj.name } --- ${ obj.age }`
    
        document.querySelector('#btn').onclick = function() {
          obj.age ++
        }
    
      </script>
    </body>
    </html>
    
  • 通过定义一个临时变量作为中转, 可以让 get / set 方法用起来就像普通属性去获取 / 修改

3.Object.defineProperty 方法 - 使用闭包进行封装 defineReactive 函数

  • 利用闭包, 来封装一个方法
  • val 局部变量被内层函数 get/ set 使用, 形成了闭包
<!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="box">
    <p></p>
    <button id="btn">修改年龄</button>
  </div>
  <script>
    const obj = {
      name: 'zs'
    }

    function defineReactive(obj, key, val) {
      Object.defineProperty(obj, key, {
        // 访问 obj.age 时这个方法会自动执行
        get() {
          // 一般会在这里收集依赖, 例如: 网页中 p / h1 / div 等标签要渲染 age 数据
          // 注意: 这里是收集这些依赖, 下面会在 set 中自动通知这些依赖来更新 DOM
          console.log(`有人访问了 ${ key } !`, val)
          return val
        },
        // 给 obj.age 赋值时这个方法会自动执行, 我们也称之为拦截
        set(newVal) {
          // 一般当数据变更时, 通知依赖项更新 DOM
          console.log(newVal)
          val = newVal
        } 
      })
    }

    defineReactive(obj, 'age', 18)
    
    document.querySelector('p').innerHTML = `${ obj.name } --- ${ obj.age }`

    document.querySelector('#btn').onclick = function() {
      obj.age ++
    }

  </script>
</body>
</html>

总结

  • 通过利用闭包的特性, 封装一个函数, 可以很好的定义对象的「响应式属性」
  • 将来 Vue 就是利用这一特性, 来实现的响应式原理

4. 响应式原理 - 简介

在这里插入图片描述

讲解

  • Vue 响应式核心就是利用了两个类, Dep 类和 Watcher
  • 每个定义在 data 中的数组、对象中都会有一个 dep 属性,访问属性的时候 get 方法会收集对应的 Watcher

在这里插入图片描述

总结

  1. 初始化 data 的时候, 调用 observe() 方法给 data 里的属性定义 get 方法和 set 方法
  2. 渲染真实 DOM 的时候, Watcher 会访问页面上使用的属性变量
  3. 由于 Object.defineProperty() 的特点, 会自动执行 get 方法, 给数据的 Dep 都加上渲染函数,每次修改数据时通知渲染 Watcher 更新视图

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

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

相关文章

go实战(1)-hello,world与包基础(1)-模块基础

目录程序结构程序代码使用和建立包建立目录模块参考中的身份验证计算哈希值go.sum文件Checksum database程序结构 声明一个main包(包是对函数进行分组的一种方法&#xff0c;它由同一目录中的所有文件组成)。 导入流行的fmt包&#xff0c;它包含格式化文本的函数&#xff0c;…

WIFI码挪车码创建生成CPS聚合流量主小程序开发

WIFI码挪车码创建生成CPS聚合流量主小程序开发 系统特点// 这不是一套普通的给别人开SAAS账号的CPS推广返利系统&#xff0c;而是一套服务商版的CPS推广返利系统&#xff01;所谓服务商版&#xff0c;就是所有CPS推广走你的渠道接口&#xff0c;除了可以给你的下级客户开账号外…

MySQL下载安装运行

方式1、MySQL 官方网站&#xff1a;http://www.mysql.com 拉到最下面&#xff1a; 方式2、Windows版 MySQL 的官方下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 配置环境变量&#xff1a;在Path中添加至“\bin”&#xff08;系统盘C盘&#xff09;形式 使用管…

【OpenCV 例程 300篇】249. 特征描述之视网膜算法(FREAK)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】249. 特征检测之视网膜算法&#xff08;FREAK&#xff09; 1. FREAK 算法简介 快速视网膜算法&#xff08;FREAK&#xff09;算法是 Alexandre Alahi 在 ICCV 2012 的论文 FREAK: Fast Retina Keyp…

1.32 Cubemx_STM32F429串口中断+空闲中断

1、简介 有时候串口接收数据时,没有帧头与帧尾,单纯使用单字节中断接收数据,不太好断帧。如果单纯使用空闲中断接收数据,当帧内数据不连续或者黏包,使用空闲中断接收就会出现接收的数据小于或者大于帧长度,比较难断帧。解决办法 方法1、单字节中断接收+空闲中断 发送命…

Spring Cache组件

《Spring Cache组件》 提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!! 《Spring Cache组件》《Spring Cache组件》1. Spring Cache组件概述2. ConcurrentHashMap缓存管理3. Cacheable详解4. Caffeine缓存管理5. 缓存更新策略6. 缓存清除策略7. 多级缓存策略…

[附源码]计算机毕业设计基于Springboot景区直通车服务系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

探究商城中的在线语音谈判功能开发

近年来&#xff0c;电子商务已经成为一种新型的商业形式&#xff0c;电子商务的发展让传统的面对面谈判发展为以互联网为依托的在线沟通&#xff0c;相较于传统的谈判方式&#xff0c;在线语音谈判方式更便捷、更高效&#xff0c;逐渐成为商务谈判的主流&#xff0c;因此该功能…

FastReport Mono 2023.1 Crack

与位于 FastReport 云服务器上的报表进行交互。特征 现在支持与 FastReport Cloud 报告生成器的部分集成。改进的报告验证器包括一个带有错误编号的新的可自定义列。添加了来自 JasperReports 的模板转换器。改进的“MSChartObject”&#xff1a; 常用设置已移至单独的编辑器。…

线程池详细介绍

线程池执行流程 线程池的状态 RUNNINGSHUTDOWNSTOPTIDYINGTERMINATED 线程池优雅关闭 线程池有两个关闭方法&#xff0c;shutdown()和shutdownNow()&#xff0c;shutdown()切换到SHUTDOWN状态&#xff0c;shutdownNow()切换到STOP状态&#xff0c;当队列和线程池都为空的时候…

学习 | ANSYS经典界面在压力容器分析设计中的应用

导读&#xff1a;分析设计作为压力容器设计的重要方法&#xff0c;不仅解决了压力容器常规设计所不能解决的问题&#xff0c;而且也是压力容器设计观点与方法上的一个质的飞跃。 分析设计通常分为两类&#xff1a;应力分类法&#xff08;弹性方法&#xff09;和直接法&#xf…

基于FPGA的SD NAND图片显示实现

文章目录 0、前言 1、目标 2、图片的预处理 3、SD NAND的预处理 4、FPGA实现 4.1、详细设计 4.2、仿真 4.3、实验结果 0、前言 在上一篇文章《基于FPGA的SD卡的数据读写实现&#xff08;SD NAND FLASH&#xff09;》中&#xff0c;我们了解到了SD NAND Flash的相关知识…

大(json)文件压缩(minify)

文章目录Preface解决方案Preface 现在在做一个 GIS 地图的项目, 做过地图的应该就知道各省/市/县的json文件有多大(大部分都是经纬度数据), 就直接放前台public目录下了. 文件过大, 上传到服务器就占用很多空间, 这时候就有人提出需求, 让把这个问题处理一下. (虽然这个事情没…

mysql日志管理 、备份与恢复

目录 一、数据备份的重要性与分类 1、数据备份的重要性 2、从物理与逻辑的角度&#xff0c;备份分为 3、从数据库的备份策略角度&#xff0c;备份可分为 3.1 完全备份&#xff08;只适合第一次&#xff09; 3.2 差异备份&#xff08;用的较少&#xff0c;有丢失数据的现象…

应用 Serverless 化,让业务开发心无旁骛

我们希望让用户做得更少而收获更多&#xff0c;通过Serverless化&#xff0c;用云就像用电一样简单。”张建锋表示&#xff0c;Serverless 让云计算从一种资源真正变成一种能力&#xff0c;未来云将全面 Serverless 化&#xff0c;更加接近“电网”模式&#xff0c;按计算的调用…

使用Visual Studio Code 进行Python编程

1、下载Visual Studio Code 到微软的Visual Studio Code官方主页下载Visual Studio Code: Visual Studio: 面向软件开发人员和 Teams 的 IDE 和代码编辑器Visual Studio 开发工具和服务让任何开发人员在任何平台和语言的应用开发都更加轻松。 随时随地免费使用代码编辑器或 I…

web期末网站设计大作业:基于HTML+CSS+JavaScript制作新能源汽车企业网站

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

负载均衡四层和七层的区别

一. 什么是负载均衡 1&#xff09;负载均衡&#xff08;Load Balance&#xff09;建立在现有网络结构之上&#xff0c;它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。负载均衡有两方面的含义&#…

基于Boost库的在线搜索引擎

文章目录Boost库搜索引擎1. 项目背景2. 宏观原理3. 搜索引擎技术栈和项目环境4.正排索引vs倒排索引&#xff08;index.hpp&#xff09;1. 正排索引:数组vector<>2. 目标文档进行分词(方便倒排索引和查找)3. 倒排索引&#xff1a;unordered_map<>模拟一次查找的过程…

反向传播不香了?解读 Hinton 大佬的 Forward-Forward 算法

今天解读一篇Hinton大佬最近分享的论文。 在最近的NeurIPS2022会议上&#xff0c;图灵奖得主Hinton作为演讲嘉宾&#xff0c;分享了一个题为《The Forward-Forward Algoritm: Some Preliminary Investigations》的论文。 该论文提出了一种取代反向传播的前向-前向传播的训练方…