前端从零开始写一个简单的响应式

写一个简单的响应式。
不是vue的源码更多的是一个理解。
首先需要遍历对象,为对象的每个属性设置settergetter

function observer(obj) {
    const vm = {};
    for (const prop in obj) {
        if (Object.hasOwnProperty.call(obj, prop)) {
            const dep = new Dep();
            Object.defineProperty(vm, prop, {
                get() {
                    dep.depend();
                    return data[prop];
                },
                set(val) {
                    data[prop] = val;
                    dep.notify();
                }
            })
        }
    }
    return vm;
}

收集依赖通过Dep实例进行收集,并且收集的是Watcher实例。
Dep

class Dep {
    deps = [];
    notify() {
        const deps = this.deps;
        this.deps = [];
        for (let i = 0; i < deps.length; i++) {
            const watcher = deps[i];
            schedule.push(watcher);
        }
        schedule.nextTick();
    }
    depend() {
        watcher && this.deps.push(watcher);
    }
}

Watcher

class Watcher {
    constructor(data, prop, cb) {
        this.data = data;
        this.prop = prop;
        this.cb = cb;
        this.value = this.get();
    }
    get() {
        watcher = this;
        let value = this.data[this.prop];
        watcher = undefined;
        return value;
    }
    update() {
        const oldValue = this.value;
        this.value = this.get();
        this.cb(this.value, oldValue);
    }
}

watcher实例的执行是异步任务,并且微任务的优先级更高。需要调度器Schedule

class Schedule {
  _task = new Set();

    push(watcher) {
        this._task.add(watcher);
    }

    _run() {
        const task = this._task;
        this._task = new Set();
        for (const watcher of task) {
            watcher.update();
        }
    }

    nextTick() {
        Promise.resolve().then(this._run.bind(this));
    }
}

完整案例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <div id="first">1</div>

    <script>
        let watcher = null;

        class Schedule {
            _task = new Set();

            push(watcher) {
                this._task.add(watcher);
            }

            _run() {
                const task = this._task;
                this._task = new Set();
                for (const watcher of task) {
                    watcher.update();
                }
            }

            nextTick() {
                Promise.resolve().then(this._run.bind(this));
            }

        }
        const schedule = new Schedule();
        class Dep {
            deps = [];
            notify() {
                const deps = this.deps;
                this.deps = [];
                for (let i = 0; i < deps.length; i++) {
                    const watcher = deps[i];
                    schedule.push(watcher);
                }
                schedule.nextTick();
            }
            depend() {
                watcher && this.deps.push(watcher);
            }
        }

        class Watcher {
            constructor(data, prop, cb) {
                this.data = data;
                this.prop = prop;
                this.cb = cb;
                this.value = this.get();
            }
            get() {
                watcher = this;
                let value = this.data[this.prop];
                watcher = undefined;
                return value;
            }
            update() {
                const oldValue = this.value;
                this.value = this.get();
                this.cb(this.value, oldValue);
            }
        }




        const data = { count: 1 };

        function observer(obj) {
            const vm = {};
            for (const prop in obj) {
                if (Object.hasOwnProperty.call(obj, prop)) {
                    const dep = new Dep();
                    Object.defineProperty(vm, prop, {
                        get() {
                            dep.depend();
                            return data[prop];
                        },
                        set(val) {
                            data[prop] = val;
                            dep.notify();
                        }
                    })
                }
            }
            return vm;
        }
        const observerData = observer(data);
        const firstDOM = document.getElementById("first");
        const oWatcher = new Watcher(observerData, "count", function (val, oldVal) {
            console.log(val, oldVal);
            firstDOM.innerHTML = val;
        })
        firstDOM.onclick = function () {
            observerData.count++;
            observerData.count++;
            observerData.count++;
        }

    </script>

</body>

</html>

代码是提供一个思路,有些函数并不会进行参数兼容。 响应式的代码主要是看个意思,具体什么深度递归设置 Dep,处理循环引用这些问题不是没考虑到,因为这些代码仅仅提供给大家参考学习。 如果确实有需求的,制作一个完整的 MVVM,可以直接去看 vue 的源码。

在最近几天我把一些常见的前端手写题进行了整理,也希望能有更多的前端爱好者一起来学习和维护。

github地址 :Front-end-handwriting

我同时也将自己21年写的一个vue的音乐项目整理出来放到github上了,有兴趣的朋友可以看一下。

因为你之前努力过了,才会有今天的你。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/7077.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【软考五】数据库(做题)

该文章不适合学习数据库&#xff0c;适合考证&#xff0c;遇到实际问题的&#xff0c;不要在这儿浪费时间。切记切记 软考之数据库一、概念数据模型&#xff08;下午题常考&#xff09;二、结构数据模型关系模型1、关系模型中基本术语2、关系模型中的关系完整性约束3、关系代数…

Flutter-Scaffold组件

在Flutter开发当中&#xff0c;我们可能会遇到以下的需求&#xff1a;实现页面组合使用&#xff0c;比如说有悬浮按钮、顶部菜单栏、左右抽屉侧边栏、底部导航栏等等效果。Scaffold组件可以帮我们实现上面需求说的效果。这篇博客主要分享容器组件的Scaffold组件的使用&#xff…

前后台协议联调拦截器

前后台协议联调&拦截器4&#xff0c;前后台协议联调4.1 环境准备4.2 列表功能4.3 添加功能4.4 添加功能状态处理4.5 修改功能4.6 删除功能5&#xff0c;拦截器5.1 拦截器概念5.2 拦截器入门案例5.2.1 环境准备5.2.2 拦截器开发步骤1:创建拦截器类步骤2:配置拦截器类步骤3:S…

快速玩转 CNStack 2.0 流量防护

作者&#xff1a;冠钰 云原生下的服务治理 在云原生技术的演进过程中&#xff0c;依托云原生技术能力&#xff0c;形成一个可以向下管理基础设施&#xff0c;向上管理业务应用的技术中台&#xff0c;越来越成为企业期望的云原生技术落地趋势。随着云原生技术中台 CNStack 发布…

逍遥自在学C语言 | 逻辑运算符

前言 一、人物简介 第一位闪亮登场&#xff0c;有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序猿 —— 逍遥。 二、构成和表示方式 逻辑运算符是用来比较和操作布尔值的运算符C语言中的逻辑运算符主要有3个&#xff0c;如下表所示 运…

vue echarts 画饼图

页面&#xff1a; {{--饼图--}}<template><div class"col-sm-6"><div id"mychart" :style"{width: 100%, height: 400px}"></div></div></template>pie_data: [], //饼图myChart: {},pieName: [],/** 再画…

论文阅读《LargeKernel3D: Scaling up Kernels in 3D Sparse CNNs》

论文地址&#xff1a;https://arxiv.org/pdf/2206.10555.pdf 源码地址&#xff1a;https://github.com/dvlab-research/LargeKernel3D 前言 3D 大核 CNN 设计难点主要分为两个方面&#xff1a; 模型计算效率: 增大3维卷积核时&#xff0c;参数量和计算负担的增长速度比 2D CN…

【Linux】理解Linux中硬链接和软链接

Linux中硬链接和软链接0 引言1 硬链接&#xff08;Hard Link&#xff09;1.1 让文件之间产生硬链接关系1.2 不能给目录创建硬链接2 软链接&#xff08;Sort Link&#xff09;2.1 让文件产生软链接关系2.2 目录也可以产生软链接关系2.3 软链接的应用场景3 总结0 引言 在之前的文…

蓝桥杯真题2021c++省A题解

[蓝桥杯 2021 省 A] 填空问题 试题 A&#xff1a;卡片 小蓝有很多数字卡片&#xff0c;每张卡片上都是数字 000 到 999 。 小蓝准备用这些卡片来拼一些数&#xff0c;他想从 111 开始拼出正整数&#xff0c;每拼一个&#xff0c;就保存起来&#xff0c;卡片就不能用来拼其它…

Vue3+vite2 博客前端开发

Vue3vite2 博客前端开发 文章目录Vue3vite2 博客前端开发前言页面展示代码设计卡片设计背景&#xff08;Particles.js粒子效果&#xff09;右侧个人信息与公告内容页友链总结前言 大家是否也想拥有一个属于自己的博客&#xff1f;但是如何去开发博客&#xff0c;怎样去开发一个…

【Verilog基础】二进制比较器

文章目录 一、二进制比较器1、1、一位数值比较器(是多位比较器的基础)1、2、两位数值比较器`A1A0`比`B1B0`1、3、典型数值比较器之:四位数值比较器`A3A2A1A0`比`B3B2B1B0`1、4、位数扩展数值比较器:串联、并联二、例题:四位数值比较器一、二进制比较器 1、1、一位数值比较…

一文讲清深力科工业与能源行业首选大电流 600V HVIC 高低边驱动产品SLM21814CJ-DG代替UCC27714DR 特性简述

一文讲清深力科工业与能源行业首选大电流 600V HVIC 高低边驱动产品SLM21814CJ-DG代替UCC27714DR 特性简述 SLM21814CJ-DG是一款大电流的 600V HVIC 高低边驱动产品&#xff0c;峰值拉电流为 2.5A&#xff0c;灌电流为 3.5A&#xff0c;同时可为两个通道提供 8.9V/8.2V 的欠压…

并发编程(十)-ScheduledThreadPoolExecutor源码分析

一、ScheduledThreadPoolExecutor 概述 ScheduledThreadPoolExecutor 是 Java 中的一个线程池实现&#xff0c;它继承自 ThreadPoolExecutor 类&#xff0c;并实现了 ScheduledExecutorService 接口&#xff0c;ScheduledThreadPoolExecutor内部维护了一个任务队列和一组线程&a…

代码随想录Day44

今天继续学习通过动态规划解决问题 96.不同的二叉搜索树 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5 思路…

蓝桥杯模板题目

A:::::::::::::::小王子单链表&#xff08;链表&#xff09; 题目描述 小王子有一天迷上了排队的游戏&#xff0c;桌子上有标号为 1−10 的 10 个玩具&#xff0c;现在小王子将他们排成一列&#xff0c;可小王子还是太小了&#xff0c;他不确定他到底想把那个玩具摆在哪里&…

企业电子招投标采购系统——功能模块功能描述+数字化采购管理 采购招投标

​ 功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外…

chatgpt大模型赋能人形机器人之我见

我个人的看法&#xff08;不涉及任何和他项目相关的细节或商业机密&#xff0c;仅仅是我个人的泛泛而谈&#xff09;&#xff1a; 1、从大趋势来说&#xff0c;人形机器人的灵活度和通用性确实非常的高&#xff0c;是有前景的。另外轮式足式也不是他独一例&#xff0c;像 ETH …

MySQL主从复制之多主多从部署流程—2023.04

文章目录一、多主多从实现架构图二、准备工作三、MySQL多主多从搭建流程1、修改2个主节点配置文件2、修改2个从节点配置文件3、2个主节点相互复制4、2个从节点分别复制主节点5、测试记录&#xff1a;一、多主多从实现架构图 这里是2主2从&#xff0c;下图基本例举出来的实现的…

使用树状图可视化聚类

一般情况下&#xff0c;我们都是使用散点图进行聚类可视化&#xff0c;但是某些的聚类算法可视化时散点图并不理想&#xff0c;所以在这篇文章中&#xff0c;我们介绍如何使用树状图&#xff08;Dendrograms&#xff09;对我们的聚类结果进行可视化。 树状图 树状图是显示对象…

48掌握私有云平台 OpenStack 的基本服务和使用方法,包括 Nova、Glance

Nova Nova 是 OpenStack 的计算组件&#xff0c;用于管理和调度计算资源。它可以管理虚拟机实例、安全组、弹性 IP、浮动 IP 等资源。 Nova 的基本组件 nova-api nova-api 是 Nova 的 API 服务&#xff0c;它接收来自用户和其他服务的 API 请求&#xff0c;并将它们转换为后…
最新文章