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

vue 双向绑定原理

响应式原理

Vue的核心特性之一,数据驱动视图,修改了数据之后视图随之响应更新。
Vue2是借助Object.defineProperty()实现的,而Vue3是借助proxy实现的,Proxy相比Object.defineProperty在处理数组和新增属性的响应式处理上更加方便。

双向绑定

Vue2的双向绑定是通过数据劫持结合发布/订阅模式实现的。数据响应系统的核心是观察者模式(Observer)订阅者(Dep)模式。

1. 数据劫持

Vue 通过递归遍历数据对象的所有属性,并使用Object.defineProperty方法将每个属性转换为getter/setter形式。这使得当数据属性被访问或修改时,可以触发相应的回调函数。

实现步骤:

  1. 创建Observer对象:当一个Vue实例被创建时,它会调用new Observer(value)来将数据对象转换为响应式。Observer类负责将对象的每个属性都转换为getter/setter。
  2. 定义getter和setter:对于每个属性,Observer会在属性的Object.defineProperty中定义gettersetter
  • getter:当访问属性时,getter会记录当前的依赖关系。
  • setter:当属性被修改时,setter会通知所有的依赖者更新。
  1. 递归处理嵌套属性:如果属性值是一个对象,那么会递归调用Observer类来继续转换内部属性。

2.发布/订阅模式

Vue使用了发布/订阅模式来管理依赖关系。每个数据属性都有一个对应的Dep对象,它负责收集所有依赖该属性的观察者(Watcher)

实现步骤:

  1. 创建Dep对象:当Observer创建getter时,会为每个属性创建一个Dep实例。
  2. 收集依赖:当渲染视图时,Watcher会自动收集依赖。这是通过在渲染过程中调用Dep.target来实现。
  3. 更新依赖:当属性值发生变化时,Dep会通知所有相关的Watcher更新。

3.Watcher对象

Watcher对象负责更新视图。每当一个属性被访问时,就会创建一个Watcher实例。当属性发生变化时,Watcher就会被Dep通知,从而触发更新视图的操作。

实现步骤:

  1. 创建Watcher实例:在渲染过程中,每当一个属性被访问,就会创建一个新的Watcher实例。
  2. 收集依赖:Watcher会自动收集依赖,也就是将自身添加到Dep的依赖列表中。
  3. 更新视图:当属性值发生变化时,Watcher会收到通知并执行更新逻辑。

示例代码

function observe(value) {if (!value || typeof value !== 'object') {return;}let ob = new Observer(value);
}function Observer(value) {this.value = value;this.walk(value);
}Observer.prototype.walk = function (obj) {const keys = Object.keys(obj);for (let i = 0; i < keys.length; i++) {defineReactive(obj, keys[i]);}
};function defineReactive(obj, key) {let val = obj[key];observe(val); // 递归处理嵌套属性const dep = new Dep();Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter() {if (Dep.target) {dep.addSub(Dep.target);}return val;},set: function reactiveSetter(newVal) {if (newVal === val) {return;}val = newVal;observe(newVal); // 递归处理新赋值dep.notify(); // 通知依赖更新}});
}function Dep() {this.subs = [];
}Dep.prototype.addSub = function (sub) {this.subs.push(sub);
};Dep.prototype.notify = function () {this.subs.forEach(sub => sub.update());
};// Watcher 示例
function Watcher(vm, expression, callback) {this.vm = vm;this.expression = expression;this.callback = callback;Dep.target = this;this.value = this.get();Dep.target = null;
}Watcher.prototype.get = function () {return this.vm[this.expression];
};Watcher.prototype.update = function () {const newValue = this.vm[this.expression];const oldValue = this.value;if (newValue !== oldValue) {this.callback(newValue, oldValue);}
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【文件解析漏洞】实战详解!
  • python:plotly 网页交互式数据可视化工具
  • 我是客服新手,打字很慢,怎么办?
  • OpenCV 图像处理 轮廓检测基本原理
  • JDK 8 升级 17 及 springboot 2.x 升级 3.x 指南
  • C语言 柔性数组 详解
  • 锅总详解开源组织之ASF
  • Fiddler学习笔记
  • 基于java的人居环境整治管理系统(源码+lw+部署文档+讲解等)
  • 公布一批神马爬虫IP地址,真实采集数据
  • 防止xss(跨站脚本攻击)
  • golang中struct的tag -简记
  • 枚举知识点(完结)
  • 从零开始学习机器学习,掌握AI未来的关键!
  • 嵌入式人工智能(40-基于树莓派4B的水滴传感器和火焰传感器)
  • 2019年如何成为全栈工程师?
  • JS函数式编程 数组部分风格 ES6版
  • js继承的实现方法
  • leetcode46 Permutation 排列组合
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • passportjs 源码分析
  • Python中eval与exec的使用及区别
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 第十八天-企业应用架构模式-基本模式
  • 多线程 start 和 run 方法到底有什么区别?
  • 后端_MYSQL
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 如何在 Tornado 中实现 Middleware
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • python最赚钱的4个方向,你最心动的是哪个?
  • Semaphore
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • ​iOS实时查看App运行日志
  • # 计算机视觉入门
  • (Java入门)学生管理系统
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (二)WCF的Binding模型
  • (七)c52学习之旅-中断
  • .NET CORE Aws S3 使用
  • .net core 管理用户机密
  • .NET 给NuGet包添加Readme
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .NET/C# 使用反射注册事件
  • .net和jar包windows服务部署
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .net专家(高海东的专栏)
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • /var/log/cvslog 太大
  • ::前边啥也没有
  • ?php echo ?,?php echo Hello world!;?
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @EnableWebSecurity 注解的用途及适用场景