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. devops-jenkins-Pipeline实战

    1) 配置gitlab的分支项目 点击红色标记的创建 project 项目 点击Create project创建Pipeline-demo项目 项目创建完成,然后我们创建一个Add README 然后 ...

  2. git 本地回滚到上一个版本

    linux下是 git reset --hard HEAD^ windows下是 git reset --hard HEAD"^"

  3. java高级&资深&专家面试题-行走江湖必备-持续更新ing

    行走江湖必备一份面试题,这里给大家整理了一套.0面试官最喜欢问的问题或者出场率较高的面试题,助校招或者社招路上的你一臂之力! 首先我们需要明白一个事实,招聘的一个很关键的因素是在给自己找未来的同事,同 ...

  4. C语言实现和 *.ini文件。

    本文之前由于技术不到位,写的比较挫,最近花了大半天时间写了一个高级点的版本. 这里是我写的代码,已经上传到github了.跳转到github 主要是使用了链表保存ini文件的内容,在程序运行最初会初始 ...

  5. hugo官方相关文档地址

    +++ date="2020-10-17" title="hugo官方相关文档地址" tags=["hugo"] categories=[& ...

  6. go正则

    package main import ( "fmt" "regexp" ) func main() { context1 := "3.14 1231 ...

  7. spring boot:用redis+lua限制短信验证码的发送频率(spring boot 2.3.2)

    一,为什么要限制短信验证码的发送频率? 1,短信验证码每条短信都有成本制约, 肯定不能被刷接口的乱发 而且接口被刷会影响到用户的体验, 影响服务端的正常访问, 所以既使有图形验证码等的保护, 我们仍然 ...

  8. 第一章 Linux操作系统及其历史介绍

    一.什么是操作系统 1.基本含义: 简称OS 是计算机系统中必不可少的基础系统软件,是应用程序运行和用户操作必备的基础环境 操作系统就是一个人与计算机之间的中介 2.组成方式: 操作系统的组成: 计算 ...

  9. Win10中装Win10---virtualbox虚拟机的安装及拓展

    最近在准备一档专栏时,发现我电脑中已经把一些环境配置完了,卸掉重装又显得麻烦,于是我就求助于虚拟机,虚拟机确实是个很好的东西,不久前我的一个伙伴向我请教虚拟机怎么装,发现这玩意三言两语还很难说清,于是 ...

  10. django—ORM相关

    常用的QuerySet方法 1.all() 查询表中所有数据,返回一个QuerySet对象列表 2.filter() 查询满足条件的数据,返回一个QuerySet对象列表 3.get() 查询指定的数 ...