📝 docs(code-reader): React 钩子卡片原型两个图标放左边、多值改成表
This commit is contained in:
1 parent
5ec8588c70
commit
7570701bf4
4 files changed
+6539
-4208
No files matched your search
Binary file not shown.
|
Before Width: | Height: | Size: 494 KiB After Width: | Height: | Size: 514 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.3 MiB |
+90
-64
@@ -1,7 +1,7 @@
|
|||||||
// 代码阅读 React 钩子卡片:一个 VS Code 窗口里左边是编辑器、右边是代码阅读预览,每张卡片和它那段源码的第一行对齐,
|
// 代码阅读 React 钩子卡片:一个 VS Code 窗口里左边是编辑器、右边是代码阅读预览,每张卡片和它那段源码的第一行对齐,
|
||||||
// 卡片比源码高时,编辑器在那段源码下面留空,下一段源码再和下一张卡片对齐。
|
// 卡片比源码高时,编辑器在那段源码下面留空,下一段源码再和下一张卡片对齐。
|
||||||
// 每处钩子调用都是同一种「钩子」卡片:钩子 / 类型参数 / 参数 / 返回四行照钩子签名排,各类钩子只在后面追加自己的行;
|
// 每处钩子调用都是同一种「钩子」卡片:钩子 / 类型参数 / 参数 / 返回四行照钩子签名排,各类钩子只在后面追加自己的行;
|
||||||
// 图标、描边所有钩子一样,淡底按来源分,React 自带的钩子再按作用带一个图标小标签。
|
// 左边的钩子图标、描边所有钩子一样,淡底按来源分,React 自带的钩子左边再并排一个作用图标;几处位置、几处改动都排成表。
|
||||||
// 样例源码 `src/chat/Panel.tsx` 是手写的,两张画板共用:一张画第 1–21 行,一张画第 23–60 行;钩子来自 React、第三方库、项目自己各有一处。
|
// 样例源码 `src/chat/Panel.tsx` 是手写的,两张画板共用:一张画第 1–21 行,一张画第 23–60 行;钩子来自 React、第三方库、项目自己各有一处。
|
||||||
// 颜色、窗口和卡片画法取自同目录 react.js(VS Code Dark Modern,卡片淡底 7%、描边 35%),函数小框取自同目录 rust-chain.js;
|
// 颜色、窗口和卡片画法取自同目录 react.js(VS Code Dark Modern,卡片淡底 7%、描边 35%),函数小框取自同目录 rust-chain.js;
|
||||||
// 卡片里的译文照 vscode/src/codeReader/translators/typescriptZh.ts 的中文直译,渲染大纲的说法照 vscode/src/codeReader/rules/react.ts。
|
// 卡片里的译文照 vscode/src/codeReader/translators/typescriptZh.ts 的中文直译,渲染大纲的说法照 vscode/src/codeReader/rules/react.ts。
|
||||||
@@ -46,12 +46,11 @@ const C = {
|
|||||||
// 编辑器的括号配对着色(Dark Modern 的 editorBracketHighlight.foreground1–3),按嵌套层数轮换
|
// 编辑器的括号配对着色(Dark Modern 的 editorBracketHighlight.foreground1–3),按嵌套层数轮换
|
||||||
const BRACKETS = ["#ffd700", "#da70d6", "#179fff"];
|
const BRACKETS = ["#ffd700", "#da70d6", "#179fff"];
|
||||||
|
|
||||||
// 定义处的卡片种类:上下文、自定义钩子是这次新加的,别的同 react.js;函数同 build.js。钩子调用的卡片按分类取色,见 HOOK
|
// 定义处的卡片种类:上下文是这次新加的,别的同 react.js;函数同 build.js。钩子的定义和调用都用 HOOK 的样式
|
||||||
const K = {
|
const K = {
|
||||||
import: { label: "导入", color: "#c586c0", icon: "import" },
|
import: { label: "导入", color: "#c586c0", icon: "import" },
|
||||||
fn: { label: "函数", color: "#dcdcaa", icon: "square-function" },
|
fn: { label: "函数", color: "#dcdcaa", icon: "square-function" },
|
||||||
context: { label: "上下文", color: "#4ec9b0", icon: "share-2" },
|
context: { label: "上下文", color: "#4ec9b0", icon: "share-2" },
|
||||||
hook: { label: "自定义钩子", color: "#61dafb", icon: "plug" },
|
|
||||||
component: { label: "React 组件", color: "#61dafb", icon: "atom" },
|
component: { label: "React 组件", color: "#61dafb", icon: "atom" },
|
||||||
handler: { label: "事件处理函数", color: "#dcdcaa", icon: "mouse-pointer-click" },
|
handler: { label: "事件处理函数", color: "#dcdcaa", icon: "mouse-pointer-click" },
|
||||||
render: { label: "渲染输出", color: "#89d185", icon: "layout-template" },
|
render: { label: "渲染输出", color: "#89d185", icon: "layout-template" },
|
||||||
@@ -585,7 +584,40 @@ function tools(parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 一张卡片:折叠箭头(有子块才有:`open` 展开、`closed` 收起)、种类图标、内容、右上角两个按钮。
|
* 卡片左边的一个概念图标:20px 见方,图标 16px。`bubble` 时画出它悬停的提示气泡,样子同 webview 的 data-tooltip
|
||||||
|
* (悬停浮层的底色、边框、11px 字)。气泡画在图标下方隔 6px,右边和图标右边对齐,不伸出这一格,图标那一列才不被撑宽:
|
||||||
|
* OpenPencil 里前面的兄弟节点画在上层,往上伸的气泡会被上一张卡片盖住。
|
||||||
|
*/
|
||||||
|
function conceptIcon(parent, item) {
|
||||||
|
if (!item.bubble) {
|
||||||
|
const cell = row(parent, "Concept / " + item.tip, { width: 20, height: 20, justify: "center" });
|
||||||
|
icon(cell, item.name, item.color, 16);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const cell = box(parent, "Concept / " + item.tip, { layout: "none", width: 20, height: 20 });
|
||||||
|
I(cell, { type: "icon_font", name: item.name, iconFontName: item.name, x: 2, y: 2, width: 16, height: 16, fill: solid(item.color) });
|
||||||
|
const bw = Math.ceil(widthOf(item.tip, 11, false)) + 16;
|
||||||
|
const tip = I(cell, {
|
||||||
|
type: "frame",
|
||||||
|
name: "Tooltip",
|
||||||
|
x: Math.min(Math.round(10 - bw / 2), 20 - bw),
|
||||||
|
y: 20 + 6,
|
||||||
|
width: bw,
|
||||||
|
height: 22,
|
||||||
|
layout: "horizontal",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
cornerRadius: 4,
|
||||||
|
fill: solid("#202020"),
|
||||||
|
stroke: { thickness: 1, fill: solid("#454545") },
|
||||||
|
effects: [{ type: "shadow", offsetX: 0, offsetY: 2, blur: 8, spread: 0, color: "rgba(0,0,0,0.36)" }],
|
||||||
|
});
|
||||||
|
text(tip, item.tip, { size: 11, color: C.fg, lh: 14 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一张卡片:折叠箭头(有子块才有:`open` 展开、`closed` 收起)、概念图标、内容、右上角两个按钮。
|
||||||
|
* 概念图标默认是种类图标一个,给了 `icons` 就并排画这几个(`{name, color, tip, bubble?}`)。
|
||||||
* 淡底默认用种类色,给了 `tint` 用它(钩子卡片按来源分底色)。
|
* 淡底默认用种类色,给了 `tint` 用它(钩子卡片按来源分底色)。
|
||||||
* `w` 是卡片外宽;返回内容区和内容区的宽度,属性行、表格按它断行。
|
* `w` 是卡片外宽;返回内容区和内容区的宽度,属性行、表格按它断行。
|
||||||
*/
|
*/
|
||||||
@@ -604,11 +636,13 @@ function card(parent, kind, w, o) {
|
|||||||
const fold = row(node, "Fold", { width: 14, height: 20, justify: "center" });
|
const fold = row(node, "Fold", { width: 14, height: 20, justify: "center" });
|
||||||
if (opt.fold)
|
if (opt.fold)
|
||||||
icon(fold, opt.fold === "open" ? "chevron-down" : "chevron-right", C.desc, 14);
|
icon(fold, opt.fold === "open" ? "chevron-down" : "chevron-right", C.desc, 14);
|
||||||
const kindBox = row(node, "Kind / " + kind.label, { width: 20, height: 20, justify: "center" });
|
const icons = opt.icons || [{ name: kind.icon, color: kind.color, tip: kind.label }];
|
||||||
icon(kindBox, kind.icon, kind.color, 16);
|
const concepts = row(node, "Concepts", { width: "fit_content", height: 20, gap: 2 });
|
||||||
|
for (const item of icons) conceptIcon(concepts, item);
|
||||||
const content = col(node, "Content", { gap: 3 });
|
const content = col(node, "Content", { gap: 3 });
|
||||||
tools(node);
|
tools(node);
|
||||||
return { node, content, w: w - 18 - 24 - 30 - 10 - 46, bg, labelW: opt.labelW || 76 };
|
const iconsW = icons.length * 20 + (icons.length - 1) * 2;
|
||||||
|
return { node, content, w: w - 18 - 14 - iconsW - 46 - 30, bg, labelW: opt.labelW || 76 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 属性表的一行:左边说明色的标签,右边值。`value` 是着色的段、字符串,或自己画的函数 `(frame, width)`。 */
|
/** 属性表的一行:左边说明色的标签,右边值。`value` 是着色的段、字符串,或自己画的函数 `(frame, width)`。 */
|
||||||
@@ -765,7 +799,7 @@ function reducerCard(parent, w) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function hookCard(parent, w) {
|
function hookCard(parent, w) {
|
||||||
const ctx = card(parent, K.hook, w, { name: "useChatSession", fold: "open" });
|
const ctx = card(parent, HOOK, w, { name: "useChatSession", fold: "open", tint: ORIGIN.own });
|
||||||
nameProp(ctx, "useChatSession", C.fn, [EXPORTED]);
|
nameProp(ctx, "useChatSession", C.fn, [EXPORTED]);
|
||||||
prop(ctx, "参数", px("1 个", C.desc), { mono: false, fold: "open" });
|
prop(ctx, "参数", px("1 个", C.desc), { mono: false, fold: "open" });
|
||||||
table(ctx, [{ name: "名称", color: C.variable }, { name: "类型", color: C.type }], [["id", cx("字符串")]]);
|
table(ctx, [{ name: "名称", color: C.variable }, { name: "类型", color: C.type }], [["id", cx("字符串")]]);
|
||||||
@@ -775,11 +809,11 @@ function hookCard(parent, w) {
|
|||||||
|
|
||||||
// ─── 钩子调用:基础卡片加扩展行 ──────────────────────────────────────────────
|
// ─── 钩子调用:基础卡片加扩展行 ──────────────────────────────────────────────
|
||||||
|
|
||||||
// 所有钩子卡片同一个图标、同一个描边色;淡底按钩子从哪来分:React 自带、第三方库、项目里自己写的
|
// 所有钩子卡片左边第一个图标、描边都一样;淡底按钩子从哪来分:React 自带、第三方库、项目里自己写的
|
||||||
const HOOK = { label: "钩子", color: "#b180d7", icon: "fishing-hook" };
|
const HOOK = { label: "钩子", color: "#b180d7", icon: "fishing-hook" };
|
||||||
const ORIGIN = { react: "#61dafb", library: "#e5c07b", own: "#89d185" };
|
const ORIGIN = { react: "#61dafb", library: "#e5c07b", own: "#89d185" };
|
||||||
|
|
||||||
// React 自带钩子的作用,同 React 类型定义里钩子的分组:钩子名后面的小标签带这个图标
|
// React 自带钩子的作用,同 React 类型定义里钩子的分组:卡片左边第二个图标,中性灰,悬停显示名字
|
||||||
const ROLE = {
|
const ROLE = {
|
||||||
state: { label: "状态", icon: "toggle-right" },
|
state: { label: "状态", icon: "toggle-right" },
|
||||||
effect: { label: "副作用", icon: "zap" },
|
effect: { label: "副作用", icon: "zap" },
|
||||||
@@ -797,23 +831,6 @@ const changed = (name) => [seg(name, C.variable), seg(" 变化时", C.keyword)];
|
|||||||
const ON_MOUNT = [seg("仅挂载时", C.keyword)];
|
const ON_MOUNT = [seg("仅挂载时", C.keyword)];
|
||||||
const NO_DEPS = [seg("没写,", C.desc), seg("每次渲染后", C.keyword)];
|
const NO_DEPS = [seg("没写,", C.desc), seg("每次渲染后", C.keyword)];
|
||||||
|
|
||||||
/** 中性色的小标签,可以带一个图标:作用、库名、「浏览器绘制前」。 */
|
|
||||||
function plainTag(parent, label, bg, iconName) {
|
|
||||||
const pill = row(parent, "Tag / " + label, {
|
|
||||||
width: "fit_content",
|
|
||||||
height: 18,
|
|
||||||
padding: [0, 5, 0, iconName ? 4 : 5],
|
|
||||||
gap: 3,
|
|
||||||
radius: 4,
|
|
||||||
fill: mix("#ffffff", bg, 0.06),
|
|
||||||
stroke: mix("#ffffff", bg, 0.2),
|
|
||||||
});
|
|
||||||
if (iconName)
|
|
||||||
icon(pill, iconName, C.desc, 11);
|
|
||||||
text(pill, label, { size: 11, color: C.desc, lh: 16, weight: 500 });
|
|
||||||
return pill;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 函数参数收成的小框:朝右的折叠箭头,写「函数 (参数) · N 句」,没参数时不写括号;同调用链原型的闭包小框。 */
|
/** 函数参数收成的小框:朝右的折叠箭头,写「函数 (参数) · N 句」,没参数时不写括号;同调用链原型的闭包小框。 */
|
||||||
function fnBox(params, count) {
|
function fnBox(params, count) {
|
||||||
const segs = [seg("函数", C.desc)]
|
const segs = [seg("函数", C.desc)]
|
||||||
@@ -837,25 +854,37 @@ function fnBox(params, count) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 一段代码后面跟一句灰字(「1 秒后」「在过渡里」)。 */
|
||||||
|
function codeWithNote(code, note) {
|
||||||
|
return cx(code).concat(note ? [seg(" " + note, C.desc)] : []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一处或几处「位置 | 写法」的表(在哪改、在哪派发、用在、调用位置):位置都能点过去,写法照译。
|
||||||
|
* `rows` 每项是 `[位置, 写法, 灰字?]`。
|
||||||
|
*/
|
||||||
|
function placesRow(ctx, label, rows) {
|
||||||
|
prop(ctx, label, px(`${rows.length} 个`, C.desc), { mono: false, fold: "open" });
|
||||||
|
table(ctx, [{ name: "位置" }, { name: "写法" }], rows.map(([where, how, note]) => [[link(where, HOOK.color)], codeWithNote(how, note)]));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 钩子调用的卡片,所有钩子共用一种:钩子 / 类型参数 / 参数 / 返回四行照钩子签名排,没有的行不显示,
|
* 钩子调用的卡片,所有钩子共用一种:钩子 / 类型参数 / 参数 / 返回四行照钩子签名排,没有的行不显示,
|
||||||
* `extend` 在后面追加这类钩子自己的行。图标、描边所有钩子一样,淡底按来源取:
|
* `extend` 在后面追加这类钩子自己的行。左边第一个图标、描边所有钩子一样,淡底按来源取:
|
||||||
* React 自带的(给 `role`)钩子名后面跟作用小标签,第三方库的(给 `lib`)跟库名小标签,自己写的(`own`)不跟小标签、钩子名能点到定义。
|
* React 自带的(给 `role`)左边再并排一个作用图标;第三方库的(`lib`)、自己写的(`own`)只有钩子图标,自己写的钩子名能点到定义。
|
||||||
|
* `roleTip` 换掉作用图标的悬停文字,`bubble` 画出悬停时的提示气泡。
|
||||||
* `fold` 表示有函数参数,函数体子块收起。`params` 每项是「参数 | 值」,`returns` 每项是「名称 | 是什么」,格子同 [table]。
|
* `fold` 表示有函数参数,函数体子块收起。`params` 每项是「参数 | 值」,`returns` 每项是「名称 | 是什么」,格子同 [table]。
|
||||||
*/
|
*/
|
||||||
function hookCall(parent, w, h) {
|
function hookCall(parent, w, h) {
|
||||||
const tint = h.own ? ORIGIN.own : h.lib ? ORIGIN.library : ORIGIN.react;
|
const tint = h.own ? ORIGIN.own : h.lib ? ORIGIN.library : ORIGIN.react;
|
||||||
const ctx = card(parent, HOOK, w, { name: h.name + " · " + h.target, fold: h.fold ? "closed" : null, labelW: HOOK_LABEL_W, tint });
|
const icons = [{ name: HOOK.icon, color: HOOK.color, tip: HOOK.label }];
|
||||||
|
if (h.role)
|
||||||
|
icons.push({ name: h.role.icon, color: C.desc, tip: h.roleTip || h.role.label, bubble: h.bubble });
|
||||||
|
const ctx = card(parent, HOOK, w, { name: h.name + " · " + h.target, fold: h.fold ? "closed" : null, labelW: HOOK_LABEL_W, tint, icons });
|
||||||
const line = row(ctx.content, "Prop / 钩子", { gap: 12, align: "start" });
|
const line = row(ctx.content, "Prop / 钩子", { gap: 12, align: "start" });
|
||||||
const key = row(line, "Key", { width: ctx.labelW, height: 20 });
|
const key = row(line, "Key", { width: ctx.labelW, height: 20 });
|
||||||
text(key, "钩子", { size: 12.5, color: C.desc, lh: 20 });
|
text(key, "钩子", { size: 12.5, color: C.desc, lh: 20 });
|
||||||
const value = row(line, "Value", { gap: 6, height: 20 });
|
text(line, [seg(h.name, C.fn, h.own ? { w: 600, u: true } : { w: 600 })], { mono: true });
|
||||||
text(value, [seg(h.name, C.fn, h.own ? { w: 600, u: true } : { w: 600 })], { mono: true });
|
|
||||||
if (h.role)
|
|
||||||
plainTag(value, h.role.label, ctx.bg, h.role.icon);
|
|
||||||
if (h.lib)
|
|
||||||
plainTag(value, h.lib, ctx.bg);
|
|
||||||
for (const label of h.tags || []) plainTag(value, label, ctx.bg);
|
|
||||||
if (h.typeArg)
|
if (h.typeArg)
|
||||||
prop(ctx, "类型参数", cx(h.typeArg));
|
prop(ctx, "类型参数", cx(h.typeArg));
|
||||||
if (h.params) {
|
if (h.params) {
|
||||||
@@ -870,33 +899,42 @@ function hookCall(parent, w, h) {
|
|||||||
h.extend(ctx);
|
h.extend(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 副作用的扩展行:用到、改动、清理函数(有才写)。 */
|
/** 副作用的扩展行:改动(「改了 | 写法」表,没改动不显示)、清理函数(有才写)。 */
|
||||||
function effectRows(o) {
|
function effectRows(o) {
|
||||||
return (ctx) => {
|
return (ctx) => {
|
||||||
prop(ctx, "用到", o.uses);
|
if (o.changes) {
|
||||||
prop(ctx, "改动", o.changes, { mono: o.changesMono !== false });
|
prop(ctx, "改动", px(`${o.changes.length} 个`, C.desc), { mono: false, fold: "open" });
|
||||||
|
table(ctx, [{ name: "改了" }, { name: "写法" }], o.changes.map(([what, how]) => [what, cx(how)]));
|
||||||
|
}
|
||||||
if (o.cleanup)
|
if (o.cleanup)
|
||||||
prop(ctx, "清理函数", cx(o.cleanup));
|
prop(ctx, "清理函数", cx(o.cleanup));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 改了什么:状态、引用前面写上是哪种。 */
|
||||||
|
const stateOf = (name) => [seg("状态 ", C.fg), seg(name, C.variable)];
|
||||||
|
const refOf = (name) => [seg("引用 ", C.fg), seg(name, C.variable)];
|
||||||
|
|
||||||
// ─── 钩子调用:样例里的每一处 ────────────────────────────────────────────────
|
// ─── 钩子调用:样例里的每一处 ────────────────────────────────────────────────
|
||||||
|
|
||||||
// 别的卡片点到副作用时用的名字;链接色是它要跳去的钩子卡片的颜色
|
// 别的卡片点到副作用时用的名字
|
||||||
const SESSION_EFFECT = "副作用「id 变化时」";
|
const SESSION_EFFECT = "副作用「id 变化时」";
|
||||||
const OPEN_EFFECT = "副作用「open 变化时」";
|
const OPEN_EFFECT = "副作用「open 变化时」";
|
||||||
const MOUNT_EFFECT = "副作用「仅挂载时」";
|
const MOUNT_EFFECT = "副作用「仅挂载时」";
|
||||||
|
const SET_TIMER = "timer.current = window.setTimeout(…)";
|
||||||
|
const PUSH_MESSAGE = "setMessages(m => [...m, e.data])";
|
||||||
|
|
||||||
/** 第 14 行:自定义钩子里的 `useState`。 */
|
/** 第 14 行:自定义钩子里的 `useState`,作用图标画出悬停气泡。 */
|
||||||
function messagesStateHook(parent, w) {
|
function messagesStateHook(parent, w) {
|
||||||
hookCall(parent, w, {
|
hookCall(parent, w, {
|
||||||
role: ROLE.state,
|
role: ROLE.state,
|
||||||
|
bubble: true,
|
||||||
name: "useState",
|
name: "useState",
|
||||||
target: "messages",
|
target: "messages",
|
||||||
typeArg: "Message[]",
|
typeArg: "Message[]",
|
||||||
params: [["initialState", cx("空数组")]],
|
params: [["initialState", cx("空数组")]],
|
||||||
returns: [["messages", "当前值"], [px("setMessages", C.fn), "修改函数"]],
|
returns: [["messages", "当前值"], [px("setMessages", C.fn), "修改函数"]],
|
||||||
extend: (ctx) => prop(ctx, "在哪改", [link(SESSION_EFFECT, HOOK.color), seg(" 里的 ", C.fg)].concat(cx("ws.onmessage"))),
|
extend: (ctx) => placesRow(ctx, "在哪改", [[SESSION_EFFECT, PUSH_MESSAGE, "ws.onmessage 里"]]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -908,7 +946,7 @@ function sessionEffectHook(parent, w) {
|
|||||||
target: "id 变化时",
|
target: "id 变化时",
|
||||||
fold: true,
|
fold: true,
|
||||||
params: [["effect", fnBox(null, 3)], ["deps", changed("id")]],
|
params: [["effect", fnBox(null, 3)], ["deps", changed("id")]],
|
||||||
extend: effectRows({ uses: px("id", C.variable), changes: [seg("状态 ", C.fg), seg("messages", C.variable)], cleanup: "ws.close()" }),
|
extend: effectRows({ changes: [[stateOf("messages"), PUSH_MESSAGE]], cleanup: "ws.close()" }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,7 +987,7 @@ function openStateHook(parent, w) {
|
|||||||
target: "open",
|
target: "open",
|
||||||
params: [["initialState", [seg("首次渲染时调用 ", C.fg)].concat(cx("readOpen(id)"))]],
|
params: [["initialState", [seg("首次渲染时调用 ", C.fg)].concat(cx("readOpen(id)"))]],
|
||||||
returns: [["open", "当前值"], [px("setOpen", C.fn), "修改函数"]],
|
returns: [["open", "当前值"], [px("setOpen", C.fn), "修改函数"]],
|
||||||
extend: (ctx) => prop(ctx, "在哪改", [link("toggle", C.fn), seg("、", C.fg), link(OPEN_EFFECT, HOOK.color)]),
|
extend: (ctx) => placesRow(ctx, "在哪改", [["toggle", "setOpen(next)"], [OPEN_EFFECT, "setOpen(假)", "1 秒后"]]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,7 +1004,7 @@ function reducerHook(parent, w) {
|
|||||||
["'add'", [seg("count", C.variable), seg(" 加 ", C.fg), seg("1", C.number)]],
|
["'add'", [seg("count", C.variable), seg(" 加 ", C.fg), seg("1", C.number)]],
|
||||||
[px("其他", C.desc), px("不变", C.fg)],
|
[px("其他", C.desc), px("不变", C.fg)],
|
||||||
]);
|
]);
|
||||||
prop(ctx, "在哪派发", [link("toggle", C.fn), seg("(", C.fg), seg("'add'", C.string), seg(")", C.fg)]);
|
placesRow(ctx, "在哪派发", [["toggle", "dispatch({ type: 'add' })"]]);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -990,7 +1028,7 @@ function boxRefHook(parent, w) {
|
|||||||
returns: [["boxRef", "引用对象"]],
|
returns: [["boxRef", "引用对象"]],
|
||||||
extend: (ctx) => {
|
extend: (ctx) => {
|
||||||
prop(ctx, "指向", [seg("<div>", C.nativeTag), seg(" 元素", C.fg)]);
|
prop(ctx, "指向", [seg("<div>", C.nativeTag), seg(" 元素", C.fg)]);
|
||||||
prop(ctx, "用在", [seg("<div>", C.nativeTag), seg(" 的 ref 属性、", C.fg), link(MOUNT_EFFECT, HOOK.color)]);
|
placesRow(ctx, "用在", [["<div>", "ref={boxRef}"], [MOUNT_EFFECT, "boxRef.current?.scrollTo(0, 0)"]]);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1003,10 +1041,7 @@ function timerHook(parent, w) {
|
|||||||
typeArg: "数值",
|
typeArg: "数值",
|
||||||
params: [["initialValue", [seg("没写,", C.desc), seg("未定义", C.number)]]],
|
params: [["initialValue", [seg("没写,", C.desc), seg("未定义", C.number)]]],
|
||||||
returns: [["timer", "引用对象"]],
|
returns: [["timer", "引用对象"]],
|
||||||
extend: (ctx) => {
|
extend: (ctx) => placesRow(ctx, "用在", [[OPEN_EFFECT, SET_TIMER], [OPEN_EFFECT + "的清理函数", "clearTimeout(timer.current)"]]),
|
||||||
prop(ctx, "写入", [link(OPEN_EFFECT, HOOK.color)]);
|
|
||||||
prop(ctx, "读取", [link(OPEN_EFFECT, HOOK.color), seg(" 的清理函数", C.fg)]);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1033,7 +1068,7 @@ function toggleHook(parent, w) {
|
|||||||
fold: true,
|
fold: true,
|
||||||
params: [["callback", fnBox([seg("next", C.variable), seg(": ", C.fg), seg("布尔", C.type)], 2)], ["deps", ON_MOUNT]],
|
params: [["callback", fnBox([seg("next", C.variable), seg(": ", C.fg), seg("布尔", C.type)], 2)], ["deps", ON_MOUNT]],
|
||||||
returns: [[px("toggle", C.fn), "记住的函数"]],
|
returns: [[px("toggle", C.fn), "记住的函数"]],
|
||||||
extend: (ctx) => prop(ctx, "调用位置", [link("handleClick", C.fn)]),
|
extend: (ctx) => placesRow(ctx, "调用位置", [["handleClick", "toggle(open 不成立)", "在过渡里"]]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,15 +1080,7 @@ function openEffectHook(parent, w) {
|
|||||||
fold: true,
|
fold: true,
|
||||||
params: [["effect", fnBox(null, 2)], ["deps", changed("open")]],
|
params: [["effect", fnBox(null, 2)], ["deps", changed("open")]],
|
||||||
extend: effectRows({
|
extend: effectRows({
|
||||||
uses: [seg("open", C.variable), seg("、", C.fg), seg("timer", C.variable)],
|
changes: [[stateOf("open"), "setOpen(假)"], [refOf("timer"), SET_TIMER]],
|
||||||
changes: [
|
|
||||||
seg("状态 ", C.fg),
|
|
||||||
seg("open", C.variable),
|
|
||||||
seg("(1 秒后设为 ", C.fg),
|
|
||||||
seg("假", C.number),
|
|
||||||
seg(")、引用 ", C.fg),
|
|
||||||
seg("timer", C.variable),
|
|
||||||
],
|
|
||||||
cleanup: "clearTimeout(timer.current)",
|
cleanup: "clearTimeout(timer.current)",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -1066,19 +1093,18 @@ function renderEffectHook(parent, w) {
|
|||||||
target: "每次渲染后",
|
target: "每次渲染后",
|
||||||
fold: true,
|
fold: true,
|
||||||
params: [["effect", fnBox(null, 1)], ["deps", NO_DEPS]],
|
params: [["effect", fnBox(null, 1)], ["deps", NO_DEPS]],
|
||||||
extend: effectRows({ uses: px("total", C.variable), changes: cx("document.title") }),
|
extend: effectRows({ changes: [[cx("document.title"), "String(total)"]] }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function layoutEffectHook(parent, w) {
|
function layoutEffectHook(parent, w) {
|
||||||
hookCall(parent, w, {
|
hookCall(parent, w, {
|
||||||
role: ROLE.effect,
|
role: ROLE.effect,
|
||||||
|
roleTip: "副作用 · 浏览器绘制前执行",
|
||||||
name: "useLayoutEffect",
|
name: "useLayoutEffect",
|
||||||
target: "仅挂载时",
|
target: "仅挂载时",
|
||||||
tags: ["浏览器绘制前"],
|
|
||||||
fold: true,
|
fold: true,
|
||||||
params: [["effect", fnBox(null, 1)], ["deps", ON_MOUNT]],
|
params: [["effect", fnBox(null, 1)], ["deps", ON_MOUNT]],
|
||||||
extend: effectRows({ uses: [link("boxRef", C.variable)], changes: px("无", C.desc), changesMono: false }),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user