vue diff算法与虚拟dom知识整理(5) 手写一个自己的h函数

news2024/11/24 10:48:51

本文的意义在于教会大家如何手写一个h函数

上文中 我们简单理解了一下h函数 他的作用是构建一个虚拟的dom节点
掌握这个函数还是很有必要的 首先 你想要写出来 还是得去看原版的ts代码

这边 我们没必要把太多注意力放在TS上 所以 我们这边是看ts代码 然后 仿写js代码

我们在 案例的 node_modules 下找到 snabbdom/src/h.ts 打开这个文件
在这里插入图片描述
读h函数 你会发现 他最后 是返回的用了一个 vnode函数
在这里插入图片描述
好家伙 在这套娃呢
我们打开同目录下的vnode.ts

这个 vnode函数 看着就相对简单一些了
在这里插入图片描述
简单说 就是接了一些列参数 并给这些参数限制了类型
在ts中 sel: string | undefined 的意思就是
接受一个 参数 代理名定位以为 sel :后的内容代表 可以是string字符串类型 或者 也可以是 undefined 未定义

处理外这些参数之后 就把他们转成一个json并返回
所以 h函数最后返回vnode 就是返回一个vnode函数处理好的虚拟节点对象

对象中比较麻烦的 是这个 children 因为他存在嵌套的可能 就是 一个虚拟节点里面可能又套了一个虚拟节点 被套的虚拟节点 下面 可能还有n层这样嵌套的虚拟节点

所以 我们看h函数上面这个位置
会循环处理children 一层一层 都创建出 vonde节点
在这里插入图片描述
这里 h函数是不涉及递归的 就是用循环 一层一层往下调

这里 我们看到上面有很多的if h函数这个位置 就是涉及到 h函数重载
在这里插入图片描述
重载的概念很多后端语言都有 ts也将这种概念带入了前端开发中
就是定义很多一样名字的函数 接收的参数 类型 数量 不同 调用不同的逻辑函数
如果您不了解 可以读一下我的文章
TypeScript方法重载
上文我们演示过
知道了 h函数 有非常多的调法
在这里插入图片描述

好 那么 我们就来试着写一个自己的h函数

我们看到我们一直在写的这个按理 在根目录下的src下创建一个文件夹 叫 snabbdom

然后在我们刚创建的 snabbdom 下创建一个 h.js
然后 我们刚才也看了 h函数返回 需要一个vnode函数来处理一下格式
所以 在snabbdom下再创建一个 vnode.js
参考代码如下

export default function(sel,data,children,text,elm) {
    let key = data.key?data.key:undefined;
    return {
        sel,
        data,
        key,
        children,
        text,
        elm
    }
}

逻辑非常简单
就是 导出了一个函数 这个函数接收五个参数
然后 先定义一个局部变量 叫 key 他的赋值 用了一个三元运算符
判断 如果 data中有一个key字段 那么 就用 data里的key给key赋值
如果没有 则 key等于key:undefined
然后返回一个对象 就是 字段名 等于字段对应的值 学过ES6的朋友会理解

{
    key
}

{
    key: key
}

是一个意思

然后 我们来写刚刚创建的 h.js 内的代码

然后 首先要说明 我们这边h函数 不处理方法的重载 因为 重载这个 理解了概念 谁都可以写出来 很麻烦 而且他我觉得并不算h函数中很美观的东西
所以 我们这样写的函数 就必须要传三个参数

然后 我们 h.js编写代码如下

//引入我们刚刚写的vnode
import vnode from "./vnode";
//默认导出一个函数
export default function(a,b,c) {
    //确认调用时是否传了三个参数
    if(arguments.length != 3)
      //如果参数不是三个  抛出异常警告
      throw new Errow("对不起,本h函数必须传三个参数 我们是低配版");

    //  判断 如果传入的第三个参数 是  string或者number  表示 形态为 第一种  h(标签。属性,文本)
    if(typeof c == "string"||typeof c == 'number') {
        return vnode(a,b,undefined,c,undefined);
    //如果传的是一个数组  那么 是调的第二种形式  h(标签。属性,数组)
    }else if(Array.isArray(c)) {
        //定义一个children数组  来存一下当前这个节点的子集
        let children = [];
        //循环c这个数组
        for(let i = 0;i < c.length;i++) {
            //判断当前下标是不是一个对象  因为h函数一定会返回一个对象
            if(c[i] instanceof Object) {
                children.push(c[i]);
            }else{
                //如果不是 抛出异常提示
                throw new Errow(`第三个参数的第${(i+1)}项不是一个h函数`);
            }
        }
        //循环结束  表示children收集子集也结束了
        return vnode(a,b,children,undefined,undefined);
    //判断c是否是一个对象  如果是  表示调用了第三种  h(标签。属性,h对象)
    }else if(c instanceof Object) {
        //第三种 说明  他是唯一的子集  我们直接将他的子集放入children就好了
        return vnode(a,b,[c],undefined,undefined);
    //如果以上格式 全部都不符合  排除错误
    }else{
        throw new Errow("对不起,传入的第三个参数格式错误 请认真加粗");
    }
}

因为这个东西比较不太好去叙述 所以 我就比较努力的写注释 希望大家能通过注释来理解了
这个不叫递归 是相互嵌套 h函数的思维真的很巧妙 没有很复杂的代码 但设计思维 却人感觉很有趣 也很巧妙

然后 我们来测试三种情况
我们将 src下的 index.js 代码改写如下

import h from "./snabbdom/h";

const dom1 = h("div",{
  props: {class: "dom"}
},"文本测试");

const dom2 = h("div",{
  props: {class: "dom"}
},[
  h("div",{},"java"),
  h("div",{},"html"),
  h("div",{},[
    h("div",{},"react"),
    h("div",{},"css")
  ])
]);

const dom3 = h("div",{
  props: {class: "dom"}
},h("div",{},"java"));

console.log(dom1);
console.log(dom2);
console.log(dom3);

这里 我们传了 第三个的各种情况 文本 数组 直接一个h函数
然后 我们运行项目
在这里插入图片描述
这三种 我们都打开看一下

第一种
在这里插入图片描述
第二种
在这里插入图片描述
第三种
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Faster RCNN在pycharm中运行

文章目录 1 代码2 文件说明3 代码解析5 数据6 自制数据集6.1 创建文件夹6.2 标注图片 7 开始训练 1 代码 参考B站up主&#xff1a;霹雳吧啦Wzgit clone https://github.com/WZMIAOMIAO/deep-learning-for-image-processing 2 文件说明 首先找到faster_rcnn ├── backbone: …

PCL学习七:Features-特征

参考引用 Point Cloud Library黑马机器人 | PCL-3D点云 1. 特征描述与提取 3D 点云特征描述与提取是点云信息处理中的最基础也是最关键的部分&#xff0c;点云识别、分割、重采样、配准和曲面重建等大部分算法&#xff0c;都十分依赖特征描述与提取的结果 从尺度上来划分&…

MYSQL01高级_Linux版安装、各级别字符集、字符集与比较规则、SQL大小写规范

文章目录 ①. MySQL - linux版安装②. 字符集的相关操作③. 各级别的字符集④. 字符集与比较规则(了解)⑤. SQL大小写规范⑥. sql_mode的合理设置 ①. MySQL - linux版安装 ①. 进入mysql官网,找到安装文件 ②. 将抽取出来的文件放在linux下的opt下 MySQL Community Serv…

本周大新闻|15000nit亮度Micro OLED面世;印度市场再推行VR盒子

本周XR大新闻&#xff0c;AR方面&#xff0c;eMagin公布1.5万nit亮度的新款dPd Micro OLED&#xff1b;脑机技术AR眼镜Cognixion ONE获FDA认证&#xff1b;歌尔发布智能交互手环参考设计Link&#xff1b;Meta引入更多AR广告。 VR方面&#xff0c;23年Quest Gaming Showcase定于…

3D旋转 相册

效果展示 代码逻辑 <!doctype html> <html lang"en"> <head><meta charset"UTF-8"><meta name"Keywords" content""><meta name"Description" content""><title>3D旋…

Vue3(Vite) 通过 prism.js 实现代码高亮并实现Mac风格

prismjs漂亮的代码语法高亮插件 极致易用&#xff1a;引用 prism.css 和 prism.js&#xff0c;使用合适的 HTML5 标签&#xff08;code.language-xxxx&#xff09;&#xff0c;搞定&#xff01;天生伶俐&#xff1a;语言的 CSS 类是可继承的&#xff0c;所以你只需定义一次就能…

自动控制原理笔记-频率响应法-控制系统的频域稳定判据

目录 一、Nyquist稳定判据 1&#xff09;开环传递函数中没有积分环节&#xff08;不含s0的极点&#xff09; 2&#xff09;开环传递函数中含有积分环节&#xff08;含s0的开环极点&#xff09; 二、Bode 稳定判据 稳定的定义&#xff1a; 任何系统在扰动的作用下都会偏离原平衡…

炫技亮点 任务编排使用CompletableFuture优化业务流程

文章目录 背景CompletableFuture简介使用场景如何编排任务步骤场景一 多个任务串行执行场景二 多个步骤并行执行场景三 一个串行步骤后两个并行步骤场景四 一个步骤依赖两个并行步骤场景五 一个步骤依赖多个并行步骤同时完成场景六 一个任务依赖多个任务的任意一个完成结果 其他…

STL--stack queue deque

stack 一、stack介绍 stack是一种容器适配器&#xff0c;专门设计用于后进先出&#xff0c;其中元素仅从容器的一端插入和提取 二、stack接口 函数名称功能说明empty判断容器是否为空size返回容器容量大小top返回栈顶数据push从栈顶插入元素pop删除栈顶元素 三、stack模拟实…

【NLP开发】Python实现聊天机器人(若干在线聊天机器人)

文章目录 1、简介2、代码测试2.1 open.drea.cc2.2 api.ruyi.ai2.3 route.showapi.com2.4 api.binstd.com2.5 api.jisuapi.com2.6 api.fanyi.baidu.com2.7 aiml2.8 api.tianapi.com2.9 nlp.xiaoi.com2.10 api.qingyunke.com2.11 api.ownthink.com 结语 1、简介 AI 聊天机器人使…

Chrome远程调试

最近接触到Chrome远程调试相关内容&#xff0c;记录一下。 场景&#xff1a;使用Chrome远程调试Chromium。当能够控制目标主机执行命令之后&#xff0c;可以在该主机上建立全局代理&#xff0c;然后在自己这一边开启浏览器监听&#xff0c;接着在目标机器上执行 chrome.exe --…

使用CSS伪元素制作动感超酷的hover动画

css 有很多神奇的效果都是使用 CSS 伪元素利用视觉差来制作的&#xff0c;以前没怎么深入的研究过 css&#xff0c;这次复习 css 的知识点才恍然大悟&#xff0c;原来 css 这么 cool。 先上效果&#xff1a; 动画实现原理 这个组动画的实现原理很简单&#xff0c;前边是一个…

ptrace

前言 gdb 的核心技术就是使用 ptrace 系统调用。 ptrace NAMEptrace - process traceSYNOPSIS#include <sys/ptrace.h>long ptrace(enum __ptrace_request request, pid_t pid,void *addr, void *data);DESCRIPTIONThe ptrace() system call provides a means by w…

开关电源学习总结

本篇文章主要通过理论来大体的讲一下开关电源的设计的思考过程&#xff0c;希望对大家可以有所帮助。本人小白&#xff0c;如有质疑&#xff0c;可以评论区指出。 一、开关电源指标 1.输入电压与输入功率 在设计开关电源时&#xff0c;需要根据需求来设计输入电压和输入功率…

12 KVM虚拟机配置-配置虚拟设备(网络设备)

文章目录 12 KVM虚拟机配置-配置虚拟设备(网络设备)12.1 概述12.2 元素介绍12.3 配置示例 12 KVM虚拟机配置-配置虚拟设备(网络设备) 12.1 概述 XML配置文件可以配置虚拟网络设备&#xff0c;包括ethernet模式、bridge模式、vhostuser模式等&#xff0c;本节介绍虚拟网卡设备…

理解生成式AI

文章目录 1、专业术语2、生成式AI3、ChatGPT1. 理解LLMRNN循环神经网络Seq2Seq模型ChatGPT与Bert区别 4、模型的生成和部署 1、专业术语 LLM&#xff1a;大型语言模型 GAI&#xff1a;通用人工智能 NLP&#xff1a;自然语言处理 CNN&#xff1a;卷积神经网络 RNN&#xff…

Spark的安装和配置

Spark的安装和配置 推荐按照我的博客下载hadoop&#xff0c;spark&#xff0c;pyspark以及scala这样版本搭配更好。 如果觉得自己不会版本搭配可私聊博主。 先安装hadoop再安装spark scala的安装和配置&#xff1a;https://blog.csdn.net/weixin_41957626/article/details/1305…

集群session的共享问题

基于redis实现共享session登录 1.集群session共享的问题 session共享问题&#xff1a;多台Tomcat并不共享session存储空间&#xff0c;当请求切换到不同tomcat服务时导致数据丢失问题 替代方案应该满足&#xff1a; 数据共享 内存存储 key、value结构 2.基于redis实现ses…

QoS实验配置-基于类部署

目录 对路由进行优先级标记 配置端口信任DSCP优先级 配置流量监管 配置拥塞管理 配置拥塞避免 配置流量整形 出接口下应用队列模板 对配置进行检验 QoS基于类的方式实现管理&#xff08;通过调度0~7队列进行实现&#xff0c;一般6、7协议是预留给路由协议的&#xff0c…

macos和windows区别 macos怎么运行windows程序

在我们使用电脑时&#xff0c;重要的是电脑内应用&#xff0c;而系统不过是运行软件的“容器”。日常生活中&#xff0c;我们常见的操作系统是macos和windows&#xff0c;那么macos和windows区别在哪&#xff1f;这两款操作系统的区别很大。macos怎么运行windows程序&#xff1…