- 博客(35)
- 收藏
- 关注
原创 CSS 相对复杂但实用的margin
margin 可以理解为盒子的外边距,决定了盒子与盒子之间的距离。margin包围的盒子尺寸一般称为盒子的"外部尺寸"。外部尺寸和内部尺寸(可视尺寸)和 偏移尺寸 不同,其值可以为负,这就给margin带来了很多有意思的现象和应用,我们常用的左右布局,双飞翼布局,圣杯布局,等高布局,都可以采用负的margin盒子完成!复习一下: 外部尺寸 内部尺寸 偏移尺寸 (滚动尺寸)
2025-03-21 18:20:10
782
原创 你不知道的 CSS Padding
padding 可以简单的理解为 填充在内容盒外层的“海绵”, 当box-sizing为默认的content-box时,增加padding时会导致整个盒子变大。如果你设置box-sizing为border-box, 并且设置width,此时width是整个border-box的宽度,如果此时padding超出这个尺寸,那么width会失效,盒子被撑开!
2025-03-20 16:39:43
744
原创 聊一下CSS层叠
层叠,即页面各个元素在Z轴方向上的先后顺序,谁压着谁,谁覆盖着谁。其中z轴定义如下,也就是垂直于显示器的方向,定位元素flex子元素这里需要注意,浮动元素可以理解为漂在文档流上面,仅仅贴着文档流的,类似于水面上的救生圈,所以浮动元素的zIndex也不起作用!
2025-03-13 17:35:14
881
原创 React 源码揭秘 | bailout策略&Memo
前面的文章介绍了React 更新 render + commit的完整流程,下面来说一下一些优化策略。bailout 即 熔断策略,即在BeginWork阶段,如果递到某个节点的子树, 如果该节点的子树已经不需要更新了,即和current保持一致了,那么可以直接熔断(bailout)当前Beginwork过程,复用current的子树即可。如何确定子树不用更新了?这个取决于四要素,即current节点和新Fiber节点的我们主要看前三条,如何判断这三条是否满足bailout条件。
2025-03-03 14:29:27
1066
原创 React 源码揭秘 | Ref更新原理
Ref主要作用于HostComponent组件,用来获取其真实的DOM节点。除此以外,我们也通常用useRef等hooks来维护一个稳定的值,并且在该值改变的时候不触发更新。
2025-02-27 14:30:58
929
原创 React 源码揭秘 | Effect更新流程
前面的文章介绍了 hooks和commit流程,算是前置知识,这篇来讨论一下useEffect的原理。useEffect用来处理副作用,比如网络请求,dom操作等等, 其本质也是个hooks,包含hooks的memorizedState, updateQueue, next。
2025-02-26 19:42:32
827
原创 React 源码揭秘 | commit流程
前面文章所描述的都发生在render过程中。React包含两个过程,即render和commit过程,其中render过程是可以打断的,而commit阶段是不可打断的。commit阶段可以理解是真正的操作DOM的阶段,其消费render阶段打到Fiber节点上的Flag,并且根据Flag对真实DOM元素进行更新,删除,插入等操作。先来复习一下Flag,我们知道,commit包含两个子阶段,即:Mutation阶段: 此阶段主要进行DOM的更新操作,包含DOM的增删改,以及Ref的更新阶段。
2025-02-26 16:53:37
1054
原创 React 源码揭秘 | hooks原理
上篇我们说了updateQueue的实现原理,这篇我们说一下hooks,fiberHooks实现可以在找到。老生常谈的问题,为什么hooks有顺序,hook函数怎么知道你在哪运行的hooks?下面我们逐一讨论。
2025-02-25 18:46:25
691
原创 React 源码揭秘 | 更新队列
前面几篇遇到updateQueue的时候,我们把它先简单的当成了一个队列处理,这篇我们来详细讨论一下这个更新队列。有关updateQueue中的部分,可以见源码。
2025-02-24 19:06:30
918
原创 React 源码揭秘 | lane模型
lane即车道的意思,其本质是个二进制的数字类型,其定义如下: (fiberLanes.ts)/** 单车道 *//** 多车道 (优先级合集) */可以看到,单个lane只能有一位是1,其余都是0,每个lane优先级1的位置都不同,互相没有重叠,数字越小,即1越靠前,优先级越高。多个lane的或运算代表批的概念 即lanes,如表示所有的Transition优先级所占用的lane的合集。
2025-02-20 19:14:20
546
原创 React 源码揭秘 | CompleteWork “归“的过程
上篇说了BeginWork的流程,我们继续看workLoop.ts/performUnitOfWork函数当一个Fiber节点的beginwork流程结束后,当前节点的pendingProps以及使用完成,将其保存在memorizedProps。
2025-02-20 15:59:59
850
原创 React源码揭秘 | 不同类型Fiber的BeginWork流程
上篇以BeginWork阶段处理HostRoot根Fiber节点为例介绍了的child reconcile协调过程,这篇主要看一下各种类型的Fiber节点在BeginWork中的处理流程。
2025-02-20 11:24:11
1187
原创 React 源码解析 | Reconcile协调过程
上篇讲了React的工作流程,这篇详细的讲一下render过程中的beginWork函数,也就是深度优先创建Fiber树中"递"的过程。beginWork函数传入当前已经创建好的Fiber节点,返回创建/复用的第一个子FIber节点,也就是wip.child在renderRoot中,在开始创建整棵FIber树之前,会先调用prepareRefreshStack创建/复用一个新的HostRootFiber。
2025-02-17 23:45:54
934
原创 React 源码揭秘 | 工作流程
上一篇介绍了React启动的入口,以及一些前置知识,这篇来说一下整个React的工作循环。render函数做了两件事,1. 是初始化合成事件,React通过对Container进行事件代理的方式管理事件,对事件进行一层封装,后面会详细讲。2. 调用updateContianer函数,此函数调用scheduler.runWithPriority传入一个立刻执行优先级的同步执行回调(runWithPriority具体细节见。
2025-02-17 17:55:34
1061
原创 React源码揭秘 | 启动入口
本文主要介绍React18版本的初始化启动过程,包含ReactElement元素的创建,createRoot如何创建根节点,以及Fiber树的基本结构,算是揭秘React核心原理的前置知识总结。
2025-02-17 15:52:22
1092
原创 React源码揭秘 | scheduler 并发更新原理
React 18增加了并发更新特性,开发者可以通过useTransition等hooks延迟执行优先级较低的更新任务,以达到页面平滑切换,不阻塞用户时间的目的。其实现正是依靠scheduler库。scheduler是一个依赖时间片分片的任务调度器,React团队将其单独发包,你可以通过以下指令来单独使用。在CPU密集操作中(如大量echarts数据补点等)可以借助scheduler将大的任务拆分成子任务运行,并且不阻塞渲染引擎以及用户事件。
2025-02-12 17:10:24
1197
原创 Proxy vs DefineProperty
几年前校招面试的时候被问过一个问题,Vue3/Vue2 如何实现数据和UI的同步,其区别是什么,Vue3的方式优势是什么?当时背了八股,默写了一通不知所云的代码,面试没过,再也没写过Vue。今天拿出点时间来写一下这个问题的前因后果,也算是做个笔记吧。
2025-02-10 18:07:55
851
原创 关于手写promise的一点补充
这样看上去没问题,但是我们需要注意,这里的then方法是在MyPromise对象上的,对于其他非MyPromise类型的thenable,是没有实现这个then方法的,其then方法可能没有循环调用的功能,所以只能实现单层的then调用,所以我们需要做的就是,在鸭子检测后判断。2. 如果是 非MyPromise类型的thenable,则调用其then方法,在成功的回调中再次调用_handleThenable 递归处理。1. 如果thenable是MyPromise类型,直接调用then方法。
2024-09-30 10:50:07
950
原创 填坑,从零带你手写Promise (typescript)
手撸promise之前,我们先用ts对我们自己的promise进行简单的类型定义观察一下浏览器提供的Promise对象:在Promise对象本身上,包含了记录promise对象状态的 state 以及记录结果的Result。其中state包含了 pending fulfilled rejected 三个状态。/** Promise状态枚举 *//** 未决策状态 *//** 成功状态 *//** 拒绝状态 */
2024-09-29 14:12:57
825
原创 从异步传染浅谈代数效应
如果你经常使用并且关注React,你一定会在不少地方见过"代数效应"(algebra effect) 这个抽象概念。可能是翻译和过度学术的缘故,我看了很多文章才大致理解,在这里简单记录一下。
2024-09-26 14:55:14
943
原创 简单聊聊宏任务和微任务
也就是说,如果你的任务代码中,包含同步阻塞代码,比如 while(true);当一帧的渲染完成后,事件循环会调度js引擎来执行宏任务队列中的任务,(这里需要强调,我们写的同步js代码,也会被封装成任务放到宏任务队列中)如果宏任务队列中存在任务,则将其加入到执行栈中执行,执行之后出栈,继续拿出来队列中的下一个任务执行!此时,第一个宏任务执行完成,弹出执行栈,执行栈为空,此时不会去取下一个宏任务,而是去检查微任务队列,执行微任务输出MicroTask1,执行后,微任务队列空,此时再去取下一个宏任务。
2024-07-04 18:13:05
944
原创 聊一下浮动
我们在排版文字的时候,通常会把开头第一个文字/字母放大处理以达到美观的效果。这样做确实能实现效果,但是如下图所示,第一行的排版受到第一个字母的内容区影响会变得很奇怪,上下行间距都会变得很宽, 解决的办法可以是设置vertical-align: text-bottom 但是上半行距也会变得很奇怪。更好的解决办法是将::first-letter 伪元素设置为浮动元素,这样就可以让文字环绕在其周围,并且不影响行间距。
2024-05-24 18:27:45
928
1
原创 简单总结一下Flex布局
flex 布局在日常开发的过程中是非常常用的了,相较于传统的流式布局,flex可以更加灵活的设置布局内元素的排布和大小。
2024-05-23 01:28:45
1508
原创 数据结构 树结构简单总结
树(Tree): 是由n(>=0)个节点组成的有限集合n = 0 时,为空树树的根Root用r表示,其余的节点可以分为m(m>=0)个不相交的有限子集T1,T2...Tm,每个子集本身又是一棵树。
2024-05-08 16:50:16
512
原创 浅谈line-height&vertical-align
在使用css调整一个行内元素对齐的时候,不知道你是不是和我一样有类似的疑问:1️⃣ 我想使用vertical-align: middle 这样的方式让行内元素水平垂直居中于容器,但是发现完全不起作用2️⃣ 我引入了一张图片,但是发现图片永远无法和背景下边缘对齐很多时候因为影响很小,我可能会忽略这些问题,或者换其他我更熟悉的方式来实现预期效果,但是当我想更深入的了解css时,这些就是绕不开的难点,下面做个简单的笔记分享一下。
2024-04-29 18:36:54
1015
原创 Typescript 基本使用
你可能会想到使用 object,但是object的检查太宽泛了,你甚至可以给object类型的变量传递一个函数, 通常,我们使用以下的方法1. 使用类型索引} = {a:1,B:2,c:3,[P :string] 为类型索引,表示属性值可以是任何字符串类型,value为any,表示值可以是任何类型2. 使用Recorda:1,B:2,c:3,Record 如上方式也可以定义一个任意类型的对象如果想要求obj中必须包含一些属性,可以使用} = {
2024-02-06 17:47:39
973
原创 JavaScript 操作符总结
这篇主要说三类操作符的使用,分别是 判等操作符 比较操作符 运算符,建议先看一下我的上一篇保证你对js中类型的转换有充分的了解。开篇先说一下在学习操作符和类型转换中get到的一些体会 "请不要 相信直觉!" 了解清楚每个操作符的运算比较流程,而不要凭借"语感"来作出判断!
2024-01-23 23:44:11
1111
1
原创 JavaScript 类型转换全面总结
Js中的类型转换一般分为 显示类型转换 和 隐式类型转换显式类型转换: 使用包装函数如 Number String Boolean 等对类型进行转换 如Number('3') = 3隐式类型转换: 不实用包装函数,动态转换。在运算符两侧类型不同的时候,会先进行隐式转换,再进行运算。如 '1'+0 = '10' [0 转换成字符串'0' 再做运算] false+10=10 [false转换成数字0 再做运算]下面具体来看类型之间的相互转换规则!
2024-01-23 18:01:20
1589
1
原创 Javascript执行&作用域全面总结
只要在当前作用域的var都收集 如下,由于没有块作用域这个概念,所以if块中的var a也属于全局作用域。
2024-01-11 19:12:40
1010
原创 为什么需要Promise?&Promise全面总结
Promise可以解释为一个许诺,你可以类比成,当你去麦当劳买汉堡,付款之后收到一个取餐码,在你的汉堡做好之后可以凭借这个号码来获得。在配餐的过程中,你不必一直等待,你可以做点别的事情,刷刷手机,当配餐结束后,你再通过号码取餐。描写成promise就是// 汉堡制作})此时你拿到了你的汉堡,可以通过then方法来进行接下来的操作,比如 吃...当然,你的汉堡也可能会因为如缺少材料等等各种因素无法按时交付,此时Promise这个许诺就是reject状态。
2024-01-07 18:25:18
1013
1
原创 迭代器和生成器总结
迭代器是一个对象,可以对另外一个对象进行遍历,称之为迭代器,其类似于光标,使用的时候不需要关心其内部的实现方法。想创建一个对象就默认带iterator,可以将迭代器工厂放到其原型链上(作为类方法)类中没有function关键字,可直接写成[Symbol.iterabor](){}的方式// 定义类迭代器工厂方法,注意是放在原型中的return {next() {.length) {return {} else {return {done: true。
2024-01-04 14:33:01
884
1
原创 浏览器原理全面总结
同时这种方式也会造成,如果在html中间引入js代码,那么js代码无法获取下方的dom元素,所以一般会将script标签放到html body的最下方,但是造成的问题是,在html代码都解析完成之后再去下载,解析,执行js,也会增加渲染的时间,能否让下载提前的情况下,也能最后运行js代码。浏览器会维护一个渲染队列,每次对布局有修改,都会push进队列中,等到队列数量够多或者达到一定时间flush队列,生成一个渲染任务,加入到事件循环中,等待js引擎让出主线程后,渲染引擎接入,完成渲染。
2024-01-03 12:01:46
920
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人