📝 docs(code-reader): React 钩子原型的函数参数一律收成 fold,函数体展开成子块
This commit is contained in:
1 parent
67e8a77f5d
commit
a139341132
5 files changed
+3582
-3087
No files matched your search
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 271 KiB After Width: | Height: | Size: 271 KiB |
+7
-3
@@ -53,6 +53,7 @@ const K = {
|
|||||||
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" },
|
||||||
|
return: { label: "返回", color: "#89d185", icon: "corner-down-left" },
|
||||||
};
|
};
|
||||||
|
|
||||||
const MONO = "Menlo";
|
const MONO = "Menlo";
|
||||||
@@ -842,8 +843,11 @@ 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)];
|
||||||
|
|
||||||
/** 函数参数收成的小框:朝右的折叠箭头,写「函数 (参数) · N 句」,没参数时不写括号;同调用链原型的闭包小框。 */
|
/**
|
||||||
function fnBox(params, count) {
|
* 函数参数收成的小框:折叠箭头,写「函数 (参数) · N 句」,没参数时不写括号;同调用链原型的闭包小框。
|
||||||
|
* 默认收起(箭头朝右),`open` 时展开(箭头朝下),函数体是卡片下面的子块。
|
||||||
|
*/
|
||||||
|
function fnBox(params, count, open) {
|
||||||
const segs = [seg("函数", C.desc)]
|
const segs = [seg("函数", C.desc)]
|
||||||
.concat(params ? [seg(" (", C.fg)].concat(params, [seg(")", C.fg)]) : [])
|
.concat(params ? [seg(" (", C.fg)].concat(params, [seg(")", C.fg)]) : [])
|
||||||
.concat([seg(" · " + count + " 句", C.desc)]);
|
.concat([seg(" · " + count + " 句", C.desc)]);
|
||||||
@@ -859,7 +863,7 @@ function fnBox(params, count) {
|
|||||||
fill: C.input,
|
fill: C.input,
|
||||||
stroke: C.borderStrong,
|
stroke: C.borderStrong,
|
||||||
});
|
});
|
||||||
icon(pill, "chevron-right", C.desc, 13);
|
icon(pill, open ? "chevron-down" : "chevron-right", C.desc, 13);
|
||||||
text(pill, segs, { mono: true, size: 12.5, lh: 18 });
|
text(pill, segs, { mono: true, size: 12.5, lh: 18 });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+45
-6
@@ -5,6 +5,7 @@
|
|||||||
// 画板一照抄 luffy-agent-platform 的 frontend/client-nextjs/src/app/desktop/login/page.tsx 第 1–37 行,
|
// 画板一照抄 luffy-agent-platform 的 frontend/client-nextjs/src/app/desktop/login/page.tsx 第 1–37 行,
|
||||||
// 画板二是手写的三行,讲没标类型、函数形式的默认值、只取当前值三种写法;
|
// 画板二是手写的三行,讲没标类型、函数形式的默认值、只取当前值三种写法;
|
||||||
// 画板三把其它常用钩子照同一个思路画:卡片讲这个变量(或这条语句)是什么,钩子退到「来自」一行,样例是手写的搜索面板。
|
// 画板三把其它常用钩子照同一个思路画:卡片讲这个变量(或这条语句)是什么,钩子退到「来自」一行,样例是手写的搜索面板。
|
||||||
|
// 钩子收的函数参数一律只画小框「函数 · N 句」,函数体是卡片下面的子块(画板三的 visible 画成展开的样子)。
|
||||||
// 窗口、对齐、别的卡片的画法在同目录 react-shared.js,接在它后面跑:`cat react-shared.js react-state.js | op design - --script`。
|
// 窗口、对齐、别的卡片的画法在同目录 react-shared.js,接在它后面跑:`cat react-shared.js react-state.js | op design - --script`。
|
||||||
|
|
||||||
// ─── 样例源码 ────────────────────────────────────────────────────────────────
|
// ─── 样例源码 ────────────────────────────────────────────────────────────────
|
||||||
@@ -243,8 +244,32 @@ const line = (label, value, o) => (ctx) => prop(ctx, label, value, o);
|
|||||||
const fromRow = (hook, tip, linked) => (ctx) => prop(ctx, "来自", (frame) =>
|
const fromRow = (hook, tip, linked) => (ctx) => prop(ctx, "来自", (frame) =>
|
||||||
text(frame, [seg(hook, C.fn, linked ? { u: true } : {})], { mono: true, name: `${hook}(悬停:${tip})` }));
|
text(frame, [seg(hook, C.fn, linked ? { u: true } : {})], { mono: true, name: `${hook}(悬停:${tip})` }));
|
||||||
|
|
||||||
/** 收起的函数体一行:小框「函数 (参数) · N 句」,同 [fnBox]。 */
|
/** 钩子收的函数参数一行:只画小框「函数 (参数) · N 句」,同 [fnBox],函数体是卡片的子块;`open` 时小框是展开的样子。 */
|
||||||
const fnRow = (label, params, count) => (ctx) => prop(ctx, label, (frame) => fnBox(params, count).draw(frame));
|
const fnRow = (label, params, count, open) => (ctx) => prop(ctx, label, (frame) => fnBox(params, count, open).draw(frame));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一张卡片连同它展开的子块:卡片下面隔 8px 是下一层,左边一条竖线标出这一层(同编辑器、预览对齐里的子块竖线),
|
||||||
|
* `children` 在竖线右边,宽度少 20px。
|
||||||
|
*/
|
||||||
|
function withChildren(drawCard, children) {
|
||||||
|
return (parent, w) => {
|
||||||
|
const block = col(parent, "Block", { gap: 8 });
|
||||||
|
drawCard(block, w);
|
||||||
|
const level = row(block, "Level", { gap: 8, align: "start" });
|
||||||
|
const guide = col(level, "Guide", { width: 12, height: "fill_container", align: "center" });
|
||||||
|
I(guide, { type: "rectangle", name: "Line", width: 1, height: "fill_container", fill: solid(C.guide) });
|
||||||
|
const list = col(level, "Blocks", { gap: 8 });
|
||||||
|
children(list, w - 20);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 一行译文的「返回」卡片,照现有返回卡片:返回图标、绿色描边,译文按词性着色。 */
|
||||||
|
function returnCard(src) {
|
||||||
|
return (parent, w) => {
|
||||||
|
const ctx = card(parent, K.return, w);
|
||||||
|
text(ctx.content, cx(src), { mono: true, maxW: ctx.w });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** 带「N 个」和展开表的一行(参数)。 */
|
/** 带「N 个」和展开表的一行(参数)。 */
|
||||||
const tableRow = (label, cols, rows) => (ctx) => {
|
const tableRow = (label, cols, rows) => (ctx) => {
|
||||||
@@ -258,11 +283,13 @@ const changedAll = (names) => names.flatMap((name, i) => (i > 0 ? [seg("、", C.
|
|||||||
/**
|
/**
|
||||||
* 一处 useState:名称照源码写出解构(展开是「第几项 | 名称 | 说明 | 操作」,当前值查谁用了它,修改函数查谁改了它)/
|
* 一处 useState:名称照源码写出解构(展开是「第几项 | 名称 | 说明 | 操作」,当前值查谁用了它,修改函数查谁改了它)/
|
||||||
* 来自 / 状态类型(没写时「未标注」)/ 默认值。`names` 是解构出的名字,`calls` 是各项在样例里出现几次。
|
* 来自 / 状态类型(没写时「未标注」)/ 默认值。`names` 是解构出的名字,`calls` 是各项在样例里出现几次。
|
||||||
|
* 默认值是函数时 `fold` 写「closed」:函数体是卡片的子块,收起。
|
||||||
*/
|
*/
|
||||||
function stateCard(s) {
|
function stateCard(s) {
|
||||||
return valueCard({
|
return valueCard({
|
||||||
kind: STATE,
|
kind: STATE,
|
||||||
lang: VAR,
|
lang: VAR,
|
||||||
|
fold: s.fold,
|
||||||
title: s.names[0],
|
title: s.names[0],
|
||||||
name: { kind: "array", items: s.names.map((name, i) => ({ name, color: i === 0 ? C.variable : C.fn, what: ITEMS[i].what, tip: ITEMS[i].tip, calls: s.calls[i] })) },
|
name: { kind: "array", items: s.names.map((name, i) => ({ name, color: i === 0 ? C.variable : C.fn, what: ITEMS[i].what, tip: ITEMS[i].tip, calls: s.calls[i] })) },
|
||||||
bubble: s.bubble,
|
bubble: s.bubble,
|
||||||
@@ -369,7 +396,17 @@ windowOf("Prototype / React 状态 · 其他写法", WIN_W + BOARD_GAP, VARIANTS
|
|||||||
{
|
{
|
||||||
from: 2,
|
from: 2,
|
||||||
to: 2,
|
to: 2,
|
||||||
draw: stateCard({ names: ["items", "setItems"], calls: [0, 0], type: [link("Item", C.type), seg("[]", C.fg)], initial: [seg("首次渲染时调用 ", C.fg)].concat(cx("loadItems()")) }),
|
draw: stateCard({
|
||||||
|
names: ["items", "setItems"],
|
||||||
|
calls: [0, 0],
|
||||||
|
fold: "closed",
|
||||||
|
type: [link("Item", C.type), seg("[]", C.fg)],
|
||||||
|
initial: (frame) => {
|
||||||
|
const holder = row(frame, "Initial", { gap: 6, height: 20, width: "fit_content" });
|
||||||
|
text(holder, "首次渲染时调用", { mono: true });
|
||||||
|
fnBox(null, 1).draw(holder);
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
from: 3,
|
from: 3,
|
||||||
@@ -552,19 +589,21 @@ const INPUT_REF = valueCard({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const VISIBLE = valueCard({
|
// useMemo 的计算函数展开着:函数体只有一个表达式,算 1 句,子块是一张返回卡片
|
||||||
|
const VISIBLE = withChildren(valueCard({
|
||||||
kind: MEMO_VALUE,
|
kind: MEMO_VALUE,
|
||||||
lang: VAR,
|
lang: VAR,
|
||||||
|
fold: "open",
|
||||||
title: "visible",
|
title: "visible",
|
||||||
name: "visible",
|
name: "visible",
|
||||||
calls: 1,
|
calls: 1,
|
||||||
tip: "谁用了",
|
tip: "谁用了",
|
||||||
rows: [
|
rows: [
|
||||||
fromRow("useMemo", BUILTIN_TIP),
|
fromRow("useMemo", BUILTIN_TIP),
|
||||||
line("计算", cx("results.filter((r) => r.hidden 不成立)")),
|
fnRow("计算", null, 1, true),
|
||||||
line("重算时机", changedAll(["results"])),
|
line("重算时机", changedAll(["results"])),
|
||||||
],
|
],
|
||||||
});
|
}), returnCard("返回 results.filter((r) => r.hidden 不成立)"));
|
||||||
|
|
||||||
const SUBMIT = valueCard({
|
const SUBMIT = valueCard({
|
||||||
kind: MEMO_FN,
|
kind: MEMO_FN,
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user