vue3的响应式原理简单实现

vue3的响应式原理设计流程图

在这里插入图片描述
相关文件
在这里插入图片描述

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
  
  </div>
  <script type="module">
    import {
   reactive} from './reactive.js'
    import {
   effect} from './effect.js'

    const user = reactive({
   
      name:'李白',
      age:18,
      foo:{
   
        bar:'刘晓'
      }
    })
    // 开始就执行一次,展示初始数据
    effect(()=>{
   
      document.querySelector('#app').innerText = `${
     user.name}-${
     user.age}-${
     user.foo.bar}`
    })
    // 修改数据
    setTimeout(() => {
   
      user.name = '杜甫'
      setTimeout(() => {
   
        user.foo.bar = '陈华'
      }, 2000);
    }, 2000);

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

effect.js

let activeEffect;
// effect为副作用函数,更新依赖的作用
export const effect = (fn) => {
   
    const _effect = () => {
   
        activeEffect = _effect;
        fn();
    };
    _effect();
};
const targetMap = new WeakMap();
// track 收集依赖
export const track = (target, key) => {
   
    // 获取Map对象
    let depsMap = targetMap.get(target);
    if (!depsMap) {
    // 如果没有,初始化一个Map对象,并添加进去
        depsMap = new Map();
        targetMap.set(target, depsMap);
    }
    // 获取一个Set对象(一个伪数组)
    let deps = depsMap.get(key);
    if (!deps) {
   // 如果没有,初始化一个Set对象,并添加进去
        deps = new Set();
        depsMap.set(key, deps);
    }
    // console.log('deps:', deps);
    // 给相关的依赖添加副作用函数
    deps.add(activeEffect);
};
// trigger 更新依赖
export const trigger = (target, key) => {
   
    let depsMap = targetMap.get(target);
    if (!depsMap) {
   
        depsMap = new Map();
        targetMap.set(target, depsMap);
    }
    let deps = depsMap.get(key);
    if (!deps) {
   
        deps = new Set();
        depsMap.set(key, deps);
    }
    // console.log('deps:', deps);
    // 执行相关依赖内部的effect副作用函数,去更新依赖
    deps.forEach((effect) => effect());
};

reactive.js

import {
    track, trigger } from './effect.js';
const isObject = (target) => {
   
    return target !== null && typeof target === 'object';
};
export const reactive = (target) => {
   
    // Proxy数据劫持
    return new Proxy(target, {
   
        // 访问了target对象源的属性就会触发get方法
        get(target, key, receiver) {
   
            let res = Reflect.get(target, key, receiver);
            track(target, key); // 收集依赖
            if (isObject(res)) {
    // 深层次数据监测  例如:{a:1,b:3,c:{k:3}}
                return reactive(res);
            }
            return res;
        },
        // 修改了target对象源的属性值就会触发set方法
        set(target, key, value, receiver) {
   
            let res = Reflect.set(target, key, value, receiver);
            trigger(target, key); // 更新依赖
            return res;
        }
    });
};

测试:

  1. 安装下Live Server
  2. 在index.html里面右键选择Live Server打开

在这里插入图片描述
在这里插入图片描述

相关推荐

  1. Vue3响应原理

    2024-02-04 23:02:02       63 阅读
  2. Vue 3响应原理

    2024-02-04 23:02:02       64 阅读
  3. vue3 原理【详解】Proxy 实现响应

    2024-02-04 23:02:02       39 阅读
  4. vue2和vue 3 响应原理

    2024-02-04 23:02:02       31 阅读
  5. vue响应原理

    2024-02-04 23:02:02       58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-04 23:02:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-04 23:02:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-04 23:02:02       82 阅读
  4. Python语言-面向对象

    2024-02-04 23:02:02       91 阅读

热门阅读

  1. UVA-213

    2024-02-04 23:02:02       54 阅读
  2. QCoro: Qt C++ 20 协程库介绍

    2024-02-04 23:02:02       51 阅读
  3. element-ui上传图片组件封装

    2024-02-04 23:02:02       39 阅读
  4. 【如何快速上手Vue.js框架——详细介绍】

    2024-02-04 23:02:02       47 阅读
  5. 【从零开始学设计模式】第三章_工厂模式

    2024-02-04 23:02:02       47 阅读
  6. Spring- FactoryBean接口中的getObject()方法

    2024-02-04 23:02:02       55 阅读
  7. C#学习(十二)——Linq

    2024-02-04 23:02:02       43 阅读
  8. 记录一下怎么重装服务器

    2024-02-04 23:02:02       50 阅读
  9. Qt应用软件【数据篇】大小端数据转换

    2024-02-04 23:02:02       53 阅读
  10. 面试中会遇到的VUE问题

    2024-02-04 23:02:02       51 阅读