Vue3.0的响应式基于Proxy实现。具体代码如下:

  1 let targetMap = new WeakMap()
2 let effectStack = [] //存储副作用
3
4 const track = (target, key) => {
5 let effect = effectStack[effectStack.length -1]
6 if(effect){
7 //收集依赖
8 let depMap = targetMap.get(target)
9 if(depMap === undefined){
10 depMap = new Map()
11 targetMap.set(target,depMap) //effect dep 集合
12 }
13
14 let dep = depMap.get(key)
15 if(dep === undefined){
16 dep = new Set() //存储effect
17 depMap.set(key,dep)
18 }
19
20 if(!dep.has(effect)){
21 dep.add(effect)
22 effect.deps.push(dep)
23 }
24 }
25 }
26
27 const trigger = (target,key) => {
28 let depMap = targetMap.get(target)
29 if(depMap === undefined){
30 return //没有副作用
31 }
32
33 const effects = new Set()
34 const computeds = new Set()
35
36 if(key){
37 let deps = depMap.get(key)
38 deps.forEach(effect => {
39 if(effect.computed){
40 computeds.add(effect)
41 } else {
42 effects.add(effect)
43 }
44 })
45 }
46
47 effects.forEach(effect => effect())
48 computeds.forEach(computed => computed)
49 }
50
51 const handler = {
52 get(target,key,receiver){
53 track(target,key) //依赖收集
54 let ret = Reflect.get(...arguments)
55 return typeof ret == 'object' ? reactive(ret) : ret
56 },
57 set(target,key,value,receiver){
58 let info = Reflect.set(...arguments)
59 trigger(target,key) //执行副作用
60 }
61 }
62
63 const reactive = (target) => {
64 let observe = new Proxy(target,handler)
65 return observe
66 }
67
68 const effect = (fn, options={}) => {
69 let e = crateRectiveEffect(fn,options)
70 if(!options.lazy){
71 e()
72 }
73 return e
74 }
75
76 const crateRectiveEffect = (fn, options) => {
77 const effect = (...args) => {
78 return run(effect, fn, args)
79 }
80 effect.deps = []
81 effect.computed = options.computed
82 effect.lazy = options.lazy
83 return effect
84 }
85
86 //收集副作用 执行函数
87 const run = (effect, fn, args) => {
88 console.log(fn);
89 if(!effectStack.includes(effect)){
90 try{
91 effectStack.push(effect)
92 return fn(...args)
93 } finally {
94 effectStack.pop()
95 }
96 }
97 }
98
99 const computed = (fn) => {
100 const runner = effect(fn,{computed:true,lazy:true})
101 return {
102 // effect: runner,
103 get value() {
104 return runner()
105 }
106 }
107 }

调用:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>响应式</title>
<script src="main.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app"></div>
<button id="btn">click </button> <script type="text/javascript">
const root = document.getElementById('app')
const btn = document.getElementById('btn') const o = {
name:'terry',
age:1
}
let objj = reactive(o)
let double = computed(()=> objj.age*2)
effect(()=>{
root.innerHTML = `
<h1>${objj.name}今年${objj.age}岁了, ${double.value}</h1>
`
})
btn.addEventListener('click',()=>{
objj.age+=1
},false)
</script>
</body>
</html>

Vue3.0响应式原理的更多相关文章

  1. 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# ...

  2. vue2.0与3.0响应式原理机制

    vue2.0响应式原理 - defineProperty 这个原理老生常谈了,就是拦截对象,给对象的属性增加set 和 get方法,因为核心是defineProperty所以还需要对数组的方法进行拦截 ...

  3. Vue 2.0 与 Vue 3.0 响应式原理比较

    Vue 2.0 的响应式是基于Object.defineProperty实现的 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 prop ...

  4. Vue3.0 响应式数据原理:ES6 Proxy

    Vue3.0 开始用 Proxy 代替 Object.defineProperty了,这篇文章结合实例教你如何使用Proxy 本篇文章同时收录[前端知识点]中,链接直达 阅读本文您将收获 JavaSc ...

  5. Vue3.0响应式实现

    基于Proxy // 弱引用映射表 es6 防止对象不能被回收 let toProxy = new WeakMap(); // 原对象: 代理过得对象 let toRaw = new WeakMap( ...

  6. Vue2.0响应式原理以及重写数组方法

    // 重写数组方法 let oldArrayPrototype = Array.prototype; let proto = Object.create(oldArrayPrototype); ['p ...

  7. vue2与vue3实现响应式的原理区别和提升

    区别: vue2.x: 实现原理: 对象类型:Object.defineProperty()对属性的读取,修改进行拦截(数据劫持): 数组类型:通过重写更新数组的一系列方法来进行拦截(对数组的变更方法 ...

  8. vue3剖析:响应式原理——effect

    响应式原理 源码目录:https://github.com/vuejs/vue-next/tree/master/packages/reactivity 模块 ref: reactive: compu ...

  9. 由浅入深,带你用JavaScript实现响应式原理(Vue2、Vue3响应式原理)

    由浅入深,带你用JavaScript实现响应式原理 前言 为什么前端框架Vue能够做到响应式?当依赖数据发生变化时,会对页面进行自动更新,其原理还是在于对响应式数据的获取和设置进行了监听,一旦监听到数 ...

随机推荐

  1. mysql CHAR and VARCHAR 比较

    写在前面 面试的时候突然有一位面试官问,说说CHAR和VARCHAR的区别,懵逼了,想自己平常使用的时候直接把VARCHAR拿来就用,真没注意到其中的不同. 反思,为什么没有注意到他们的不同 对于my ...

  2. SpringBoot整合Mybatis 编译失败:找不到符号 程序包不存在

    问题描述:jpa不好用,转用mybatis,配置多数据源  但是配置后无法编译mvn clean install  dao层这些报错,找不到entity的包     问题解决:罪魁祸首:热部署的部分 ...

  3. 浅谈MircoPython---ESP8266

    一.连接WIFI 在Putty会话窗口输入 >>>help() 打印的消息会告诉你如何连接WIFI import network sta_if = network.WLAN(netw ...

  4. main函数标准写法

    main函数签名 C++中允许两种格式,带参数的和不带参数的: int main() int main(int argc, const char* argv[]) 和C标准不同,C++中main函数必 ...

  5. spring boot: 用redis的消息订阅功能更新应用内的caffeine本地缓存(spring boot 2.3.2)

    一,为什么要更新caffeine缓存? 1,caffeine缓存的优点和缺点 生产环境中,caffeine缓存是我们在应用中使用的本地缓存, 它的优势在于存在于应用内,访问速度最快,通常都不到1ms就 ...

  6. openresty使用redis作本地缓存

    一,为什么要使用redis作本地缓存? 1,使用缓存通常会有三层 当使用openresty作为web服务器时,我们更看重是的它可以通过lua编程的扩展能力,就openresty而言,它可以实现的功能非 ...

  7. centos8上安装phpmyadmin5

    一,下载phpmyadmin5: 1,官网地址: https://www.phpmyadmin.net/ 2,下载 [root@yjweb source]# wget https://files.ph ...

  8. 工程化编程实战callback接口学习笔记

    一.编译并运行 help.version命令执行正常,但quit命令出错 二.Debug 从命令输入到执行过程: 源代码: 更改后: 运行结果:能正确运行quit命令 Callback接口学习成果: ...

  9. 教你如何帮助前端同学快速生成API接口代码

    最近我们团队开源的后端微服务框架go-zero增长势头比较迅猛,这篇文章我讲讲go-zero对前端团队的作用,并通过一个示例来给大家演示我们是怎么做的,希望能给后端的同学也可以帮助前端同学提高开发效率 ...

  10. fiddler 实用小技巧

    1.添加查看响应时间