一些React源码的东西

一些React源码的东西

基础数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
interface ReactElement {
$$typeof: typeof Symbol.for('react.element');
type: string;
key: string|number;
ref: string|object;
props: object;
_owner: unknown;
}

type ReactNode =
| null
| boolean
| number
| string
| ReactElement
| ReactPortal
| Iterable<ReactNode>;

type ReactEmpty = null | void | boolean;

type ReactNodeList = ReactEmpty | ReactNode;

type RootType = {
render(children: ReactNodeList): void;
unmount(): void;
_internalRoot: FiberRoot;
};

const enum RootTag = {
LegacyRoot,
BlockingRoot,
ConcurrentRoot,
}

interface BaseFiberRootProperties {
tag: RootTag;
// The currently active root fiber. This is the mutable root of the tree.
current: Fiber;

// TODO
}

interface FiberRoot extends BaseFiberRootProperties {}

Fiber

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Fiber WorkTag
const enum WorkTag = {
FunctionComponent,
ClassComponent ,
IndeterminateComponent, // Before we know whether it is function or class
HostRoot , // Root of a host tree. Could be nested inside another node.
HostPortal, // A subtree. Could be an entry point to a different renderer.
HostComponent,
HostText,
Fragment,
Mode,
ContextConsumer,
ContextProvider,
ForwardRef,
Profiler,
SuspenseComponent ,
MemoComponent ,
SimpleMemoComponent ,
LazyComponent ,
IncompleteClassComponent,
DehydratedFragment ,
SuspenseListComponent ,
FundamentalComponent ,
ScopeComponent ,
OffscreenComponent ,
LegacyHiddenComponent ,
CacheComponent,
}

// A Fiber is work on a Component that needs to be done or was done. There can
// be more than one per component.
interface Fiber {
tag: WorkTag;
// 与本Fiber关联的状态
stateNode: any;
// 状态上下文
memoizedState: any;
// 状态更新队列和对应的callback
updateQueue: any;
// TODO
}

Lane

1
2
3
4
// react-reconciler/src/ReactFiberLane.new.js
type Lanes = number;
type Lane = number;
type LanePriority = number; // 0 ~ 17

UpdateQueue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// react-reconciler/src/ReactUpdateQueue.new.js

interface Update<State> {
eventTime: number;
lane: Lane;
tag: 0 | 1 | 2 | 3;
payload: any;
callback?: () => any;
next?: Update<State>;
}

interface SharedQueue<State> {
pending?: Update<State>;
}

interface UpdateQueue<State> {
baseState: State;
firstBaseUpdate?: Update<State>;
lastBaseUpdate?: Update<State>;
shared: SharedQueue<State>;
effects?: Update<State>[];
}

// TODO

一些流程

ReactElement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function createElement(
type: unknown,
config: unknown,
children?: ReactElement[]
): ReactElement;

function cloneElement(
element: ReactElement,
config: unknown,
children?: ReactElement[]
): ReactElement;

function isValidElement(object: unknown) {
return (
typeof object === "object" &&
object !== null &&
object.$$typeof === Symbol.for("react.element")
);
}

ReactDOM.render()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function render(
element: ReactElement,
container: HTMLElement | HTMLDocument,
callback: Function
): unknown {
return legacyRenderSubtreeIntoContainer(element, container, callback);
}

function legacyRenderSubtreeIntoContainer(
element: ReactElement,
container: HTMLElement | HTMLDocument,
callback: Function
): unknown {
let root: RootType = container._reactRootContainer;
let fiberRoot;

if (!root) {
root = container._reactRootContainer = new ReactDOMBlockingRoot(
container,
RootTag.LegacyRoot
);
fiberRoot = root._internalRoot;

unbatchedUpdates(() => {
updateContainer(element, fiberRoot, null, callback);
});
} else {
fiberRoot = root._internalRoot;
updateContainer(element, fiberRoot, null, callback);
}

return fiberRoot.child.stateNode;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class ReactDOMBlockingRoot {
private _internalRoot;

constructor(container: HTMLElement | HTMLDocument, tag: RootTag) {
const fiberRoot = createFiberRoot(container, tag)
// mark container as root
container[`__reactContainer$${Math.random().toString(36).slice(2)}`] = fiberRoot.current;

// 在container节点上监听所有事件冒泡,进行事件代理
// listenToAllSupportedEvents

this._internalRoot = fiberRoot;
}

render(children: ReactNodeList) {
updateContainer(children, this._internalRoot, null, null);
}

unmount() {
updateContainer(null, this._internalRoot, null, () => {
unmarkContainerAsRoot(this._internalRoot.containerInfo)
})
}
}

function createFiberRoot(container: HTMLElement | HTMLDocument, tag: RootTag): FiberRoot {
// 创建一个FiberRoot对象,填充必要属性
const root: FiberRoot = new FiberRootNode(container, tag);
// 创建一个FiberNode对象,将其node tag设置为HostRoot
const uninitializedFiber = new FiberNode(WorTag.HostRoot);
// 将新建的FiberNode对象作为当前活动的Fiber
root.current = uninitializedFiber;
// 将FiberRoot作为FiberNode的状态对象
uninitializedFiber.stateNode = root;

// ... 这里有一些根据全局开关 __EXPERIMENTAL__ 初始化 root.pooledCache 的逻辑

// 初始化fiber node 状态
const initialState = {
element: null;
}
uninitializedFiber.memoizedState = initialState;

// 初始化Fiber node updateQueue
const queue: UpdateQueue = {
baseState: uninitializedFiber.memoizedState,
}

return root;
}

updateContainer()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const enum ExecutionContext = {
NoContext = 0b0000000,
EventContext = 0b0000010,
DiscreteEventContext = 0b0000100,
LegacyUnbatchedContext = 0b0001000,
RenderContext = 0b0010000,
CommitContext = 0b0100000,
RetryAfterError = 0b1000000,
}

let executionContext = ExecutionContext.NoContext;

function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
const prevExecutionContext = executionContext;
}
Git学习笔记

Git学习笔记

基本概念

git 的所有操作基本上都是在本地执行

git 一般只添加数据

git 工作区

sequenceDiagram
  participant A as Working Directory
  participant B as Staging Area
  participant C as .git Repository
  A ->> B: git add
  B ->> C: git commit
  C ->> A: git checkout
阅读更多
《YDKJS 中卷》读书笔记

《YDKJS 中卷》读书笔记

类型

7 个内置类型:stringnumberbooleanobjectundefinedsymbolnull

1
2
3
4
5
6
7
8
9
10
11
12
typeof undefined      === "undefined";
typeof true === "boolean";
typeof 42 === "number";
typeof "42" === "string";
typeof {} === "object";
typeof null === "object";
typeof [] === "object";
typeof Symbol() === "symbol";
typeof function () {} === "function"

// 检测a是否为null
(!a && typeof a === "object")) === true;

函数对象

函数对象是object的一个子类型,具有一个内部属性[[call]],该属性使其可以被调用。

属性 含义
[[call]] 表明该对象是一个可调用对象
length 函数对象声明的行参个数
阅读更多
《YDKJS 上卷》读书笔记

《YDKJS 上卷》读书笔记

第一部分 作用域与闭包

作用域

为 JS 引擎提供支持,主要做以下 2 件事:

  1. 收集维护所声明的标识符(变量、函数)组成的一系列查询
  2. 确定当前代码对这些标识符的访问权限

JS 引擎主要通过LHSRHS从内向外(作用域可以嵌套)访问作用域。

LHS 找到标识符(变量)容器本身,然后引擎给它赋值
RHS 则是找到该容器的值,引擎使用该值进行其他操作

查询结果:

  1. RHS 找不到,抛出ReferenceError异常
  2. LHS 找不到
    1. 非严格模式下在全局作用域创建同名变量
    2. 严格模式抛出ReferenceError异常

另,TypeError异常表示作用域查询成功了但是对结果的操作是非法的,比如对不可调用对象执行调用操作、引用nullundefined的属性等。

阅读更多
JS设计模式

JS设计模式

设计模式的主题是将不变的部分与变化的部分找出来,然后将变化的地方通过模式封装起来。

基础

new、this、call、apply、bind

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function Person(name) {
this.name = name;
}

Person.prototype.getName = function () {
return this.name;
};

function New() {
// 新建一个对象,原型默认为Object.prototype
const obj = new Object();
// 取出构造函数
const construct = [].shift.call(arguments);
// 将新建的对象原型设置为构造函数对象的原型
Object.setPrototypeOf(obj, construct.prototype);
// 调用构造函数,设置构造函数的this为新建对象,返回构造函数结果
const ret = construct.apply(obj, arguments);
// 如果构造函数返回了一个对象则返回构造函数的对象,否则返回新建的对象
return typeof ret === "object" ? ret : obj;
}

const a = New(Person, "sven");
const b = new Person("sven");

console.log(a.getName()); // => sven
console.log(b.getName()); // => sven

console.log(Object.getPrototypeOf(a) === Person.prototype); // => true
阅读更多
【Flutter】Dart学习笔记

【Flutter】Dart学习笔记

基本概念

  1. 一切皆对象,包括 functions、null,所有对象都继承自Object
  2. dart 具有变量类型推导功能
  3. dart 支持泛型 List
  4. 没有publicprotectedprivate关键字,以_开头的表示库级私有
  5. 未初始化的所有变量都有初始值为null
  6. 支持finalconst,const 在编译时确定值
  7. lexically scope 语言

内建类型

  • numbers (int、double)
  • strings (UTF-16)
  • booleans
  • lists
  • sets
  • maps
  • runes
  • symbols
阅读更多
【计算机网络】数据链路层

【计算机网络】数据链路层

数据链路(data link)是两个设备进行通信的必要前提,数据链路由物理链路(硬件)和必要协议(软件)构成

现在的网卡(Network Interface Card)都实现了这些协议,即在 4 层中网卡位于两层:物理层和数据链路层。

数据链路通信的信道主要有两种:

  1. 点对点通信
  2. 广播通信

针对这两种信道,分别由点对点协议(PPP)和载波监听多点接入/碰撞检测(CSMA/CD)进行传输控制。

阅读更多
Proxmox VM 直通声卡导致宿主机无法正常启动的解决方法

Proxmox VM 直通声卡导致宿主机无法正常启动的解决方法

故障原因

使用 PVE 虚拟的 Windows 10 通过远程桌面方式播放视频,在播放的过程中音频有时断时续的现象。分析可能是虚拟的声卡性能差导致,想仿照 PVE 直通 GPU 的方式直通宿主机声卡给 Windows 10,但经过一顿操作后直通还是失败了并且导致宿主机网络功能异常无法再通过远程访问 PVE 的管理界面。这时候一定会想到可以通过宿主机外接显示器操作啊,对不起,宿主机的显卡已经直通给 Windows 10 了接上也没有信号!还有一个致命的点就是虚机是随宿主机开机启动的,宿主机重启也没有用,事情陷入了僵局……

阅读更多

《Java8实战》读书笔记

第一章 为什么要关心 Java 8

从有点修正主义的角度来看,在 Java 8 中加入 Streams 可以看作把另外两项扩充加入 Java 8 的直接原因:把代码传递给方法的简洁方式(方法引用、Lambda)和接口中的默认方法。

多核 CPU 的每个处理器内核都有独立的高速缓存。加锁需要这些高速缓存同步运行,然而这又需要在内核间进行较慢的缓存一致性协议通信。

流是一系列数据项,一次只生成一项。程序可以从输入流中一个一个读取数据项,然后以同样的方式将数据项写入输出流。一个程序的输出流很可能是另一个程序的输入流。

编程语言中的函数一词通常是指方法,尤其是静态方法;这是在数学函数,也就是没有副作用的函数之外的新含义。

在 Java 8 里写下 File::isHidden 的时候,你就创建了一个方法引用,你同样可以传递它。

Collection 主要是为了存储和访问数据,而 Stream 则主要用于描述对数据的计算。

阅读更多
TypeScript学习笔记

TypeScript学习笔记

编译器安装

现阶段 TypeScript 需要被其编译器编译为 Javascript 文件才能被浏览器识别并执行,编译器的安装非常简单,在 Node 环境下执行下面的命令就行了。

1
$npm i -g typescript

检测是否安装成功

1
2
$tsc -v
Version 4.0.3
阅读更多