Vue3.0响应式实现
基于Proxy
// 弱引用映射表 es6 防止对象不能被回收
let toProxy = new WeakMap(); // 原对象: 代理过得对象
let toRaw = new WeakMap(); // 被代理过的对象: 原对象 // 判断为对象
function isObject(val) {
return typeof val === 'object' && val !== null
}
// 区分改变数组长度还是数值
function hasOwn(target, key) {
return target.hasOwnProperty(key)
} function reactive(target) {
// 创建响应式对象
return createReactiveObject(target)
}
// 创建响应式对象
function createReactiveObject(target) {
if (!isObject(target)) {
return target
}
let proxy = toProxy.get(target); // 如果已经代理过 直接返回代理结果
if (proxy) {
return proxy;
}
if (toRaw.has(target)) { // 防止对象被多次代理
return target;
}
let baseHandler = {
// Reflect优点: 不报错 有返回值 会替代Object 上的方法
// Proxy + reflect 反射
get(target, key, receiver) {
// console.log('查询');
let result = Reflect.get(target, key, receiver);
// 收集依赖订阅 把当前key 和effect对应
track(target, key);
// result 当前获取到的值
return isObject(result) ? reactive(result) : result; // 深层次代理 多层代理 (递归)
},
set(target, key, value, receiver) {
// console.log('设置');
// 区分改变数组长度还是数值
let hadKey = hasOwn(target, key);
let oldValue = target[key];
let res = Reflect.set(target, key, value, receiver);
if (!hadKey) {
trigger(target, 'add', key);
// console.log('新增属性')
} else if (oldValue !== value) { // 表示属性修改
// console.log('修改属性')
trigger(target, 'set', key);
}//
// 设置成功返回值
return res;
},
deleteProperty(target, key) {
// console.log('删除');
let res = Reflect.deleteProperty(target, key)
return res;
}
}
let observed = new Proxy(target, baseHandler);
toProxy.set(target, observed);
toRaw.set(observed, target);
return observed
} // let proxy = reactive({name: {n: 'wyq'}});
// proxy.name.n = '王瘦瘦'
// console.log(proxy.name.n)
// let arr = [1, 2, 3];
// let proxy = reactive(arr)
// proxy.length = 100; // 发布订阅模式
// 栈结构
let activeEffectStacks = []; // 栈型结果
let targetsMap = new WeakMap(); // 集合和哈希表
function track(target, key) { // target中的key变化 执行数组方法
let effect = activeEffectStacks[activeEffectStacks.length - 1];
if (effect) { // 有对应关系 创建关联
let depsMap = targetsMap.get(target);
if (!depsMap) {
targetsMap.set(target, depsMap = new Map());
}
let deps = depsMap.get(key);
if (!deps) {
depsMap.set(key, deps = new Set());
}
if (!deps.has(effect)) {
deps.add(effect);
}
// 动态创建依赖关系
}
// 不管
} function trigger(target, type, key) {
let depsMap = targetsMap.get(target);
if (depsMap) {
let deps = depsMap.get(key);
if (deps) { // 当前key 对应effect 依次执行
deps.forEach((effect) => {
effect();
})
}
}
} // 响应式 副作用
function effect(fn) {
// 把fn包装成响应式函数
let effect = createReactiveEffect(fn);
effect(); // 先执行一次
} function createReactiveEffect(fn) {
// 高阶函数
let effect = function () { // is 创建的响应式的effect
return run(effect , fn); // 1.让fn执行 2.存入栈
};
return effect;
} function run(effect, fn) {
try {
activeEffectStacks.push(effect);
fn();
}finally {
activeEffectStacks.pop();
}
} let obj = reactive({name: 'wyq'});
effect(() => { // effect默认执行两次 默认先执行一次 依赖数据变化在执行一次
console.log(obj.name)
});
obj.name = '王瘦瘦';
obj.name = '王瘦瘦';
obj.name = 'SpongeBob';
Vue3.0响应式实现的更多相关文章
- Vue3.0工程创建 && setup、ref、reactive函数 && Vue3.0响应式实现原理
1 # 一.创建Vue3.0工程 2 # 1.使用vue-cli创建 3 # 官方文档: https://cli.vuejs.org/zh/guide/creating-a-project.html# ...
- Vue3.0响应式原理
Vue3.0的响应式基于Proxy实现.具体代码如下: 1 let targetMap = new WeakMap() 2 let effectStack = [] //存储副作用 3 4 const ...
- Vue3.0 响应式数据原理:ES6 Proxy
Vue3.0 开始用 Proxy 代替 Object.defineProperty了,这篇文章结合实例教你如何使用Proxy 本篇文章同时收录[前端知识点]中,链接直达 阅读本文您将收获 JavaSc ...
- vue2.0与3.0响应式原理机制
vue2.0响应式原理 - defineProperty 这个原理老生常谈了,就是拦截对象,给对象的属性增加set 和 get方法,因为核心是defineProperty所以还需要对数组的方法进行拦截 ...
- 简单对比vue2.x与vue3.x响应式及新功能
简单对比vue2.x与vue3.x响应式 对响应方式来讲:Vue3.x 将使用Proxy ,取代Vue2.x 版本的 Object.defineProperty. 为何要将Object.defineP ...
- 【SpringBoot】SpringBoot2.0响应式编程
========================15.高级篇幅之SpringBoot2.0响应式编程 ================================ 1.SprinBoot2.x响应 ...
- Vue 2.0 与 Vue 3.0 响应式原理比较
Vue 2.0 的响应式是基于Object.defineProperty实现的 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 prop ...
- vue2与vue3实现响应式的原理区别和提升
区别: vue2.x: 实现原理: 对象类型:Object.defineProperty()对属性的读取,修改进行拦截(数据劫持): 数组类型:通过重写更新数组的一系列方法来进行拦截(对数组的变更方法 ...
- JuCheap V2.0响应式后台管理系统模板正式发布beta版本
JuCheap V1.* 查看地址: http://blog.csdn.net/allenwdj/article/details/49155339 经过半年的努力,JuCheap后台通用响应式管理后台 ...
随机推荐
- 又一年NOIP后的一波总结
(昨天正式考完了吧...先写一下现在的感受,出成绩以及后续继续更...) 按照国际惯例,还是先讲一下故事吧. Day(~,0] 大概是跟随者时间的推进,气氛越来越紧张吧. 平时好像大家和往常一样,日常 ...
- nodejs回调大坑
最近看到nodejs,因为有一个处理里面有好几个异步操作,调入回调大坑,不禁觉得很恶心,真的很讨厌发明这种写法的人,简直反社会!!!遂转载一篇解坑的文章,原文地址:http://www.infoq.c ...
- 两台服务器共享文件Windows和Linux
最近遇到一个问题,新装的两台服务器死活就是挂载不上samba服务器上的文件,在输入mount挂载命令的时候提示只读什么的,尝试了在挂载的时候用只读的方式去挂载也是不行,最终发现了,缺少安装cifs包, ...
- 插头$DP$学习小结
插头\(DP\)学习小结 这种辣鸡毒瘤东西也能叫算法... 很优秀的一个算法. 最基本的适用范围主要是数据范围极小的网格图路径计数问题. 如果是像\(Noi2018\)那种的话建议考生在其他两道题难度 ...
- AJAX——理解XMLHttpRequest对象
AJAX大家已经都知道了,XMLHttpRequest对象则是AJAX的核心.这篇博客重点总结一下这个对象的使用. XMLHttpRequest对象的属性和方法: 属性 说明 readyState 表 ...
- js执行上下文与执行上下文栈
一.什么是执行上下文 简单说就是代码运行时的执行环境,必须是在函数调用的时候才会产生,如果不调用就不会产生这个执行上下文.在这个环境中,所有变量会被事先提出来(变量提升),有的直接赋值,有的为默认值 ...
- netty模型简介
Netty工作原理图 netty抽象出了两组线程池,BossGroup专门负责客户端 的连接,WorkerGroup专门负责网络读写. BossGroup和WorkerGroup 类型都是NioEve ...
- Springboot ,1开启配置与2.扫描包(控制层,service层)二个注解@EnableAutoConfiguration,@ComponentScan 合并成一个注解@SpringBootApplication
//@EnableAutoConfiguration//@ComponentScan(value= {"com.foen.cloud.controller.*","com ...
- delegate operator (C# reference) and => operator (C# reference)
The delegate operator creates an anonymous method that can be converted to a delegate type: C#CopyRu ...
- 最大独立点集&最小点覆盖
1.最大独立点集: 在二分图中,选最多的点,使得任意两个点之间没有直接边连接. 最大独立集= 最小边覆盖 = 总点数- 最大匹配 (条件:在二分图中) 2.最小边覆盖: 在二分图中,求最少的边,使得他 ...