NoWayOS
ZH
GitHub
菜单关闭

构建

从 React 移植

把现有的 React 界面带到 NoWayOS:用 Screen Compiler 的覆盖率报告衡量它,看清哪些照原样转换、哪些需要修改、哪些移到您的应用中,并读懂它可能给出的每一种错误。

您不必从头再来。一个 React 屏幕的大部分照写的样子就能转换:布局、文本、按钮和字段、条件和列表,还有它自己的小组件。其余的要么是简短的改写,要么是移到您的应用中的工作;在只做一件事的计算机上,那里本来就是它该在的地方。

先测量

改动任何一行之前,先问问 Screen Compiler 您的代码已经能走多远。把您的应用克隆到用 React 制作屏幕中那两个仓库的旁边,让开发容器能看到它,然后对它的源代码运行覆盖率报告:

cd nowayos-work # holds nowayos and screen-compiler
git clone https://example.com/your-app.git my-app
cd screen-compiler
make run ARGS="audit ../my-app/src"

报告读取该文件夹下的每个 .tsx 文件,并统计找到的每种语法结构:元素、props、样式属性、hooks、列表、条件、运算符和导入。每一种都会得到一个判定:

  • 在子集内:按子集允许的方式使用时即可转换;
  • 在路线图上:暂时还不能转换,报告会指出将来转换它的步骤;
  • 按设计排除:永远不会转换,报告会说明原因;
  • 未知:Screen Compiler 无法识别。未知的结构从不算作已转换。

接着列出路线图的各个步骤以及每一步被需要的次数,然后是每个文件的结果。只有 check 通过的文件才算"可以转换",所以顶部的数字就是真实的数字。报告只列出结构的名称,从不引用您的代码,因此可以放心分享。与编译器本身一样,只在您信任的代码上运行它。

什么对应什么

在 React DOM 中 在子集中
用 flexbox 布局的 <div> <Column> 或 <Row>,配合 gap、padding 和声明过的 style
<h1>、<p>、<span>、<label> 带角色的 <Text>:title、heading、body、label、caption 或 display
<button onClick={…}> <Button onClick={props.onSave}>:回调 prop 会变成一个动作
<input>、复选框、单选按钮、<select> <TextInput>、<Checkbox>、<RadioGroup>、<Select>,各有一个 id,应用通过它读取和设置值
{ready && <X/>}、? :、!ready、step === "review" 由应用设置的组和开关
items.map(…) 行:文件中所含的列表,或截取到上限的 prop 列表,props.items.slice(0, 5)
Hello, {name}! 把固定文字编译进去,围在应用填充的插槽两侧
您自己的组件和片段,在屏幕的文件中或其旁边的文件中 在构建时展开,如同把屏幕平铺写出
style={{ padding: "16px" }}, color: "var(--text-muted)" 声明过的样式属性,长度以布局单位计,颜色使用主题颜色

用 React 制作屏幕中的表格准确列出了每个组件接受什么。这些表格来自 Screen Compiler 自己的表,因此不会与它实际接受的内容脱节。

哪些移到您的应用中

设备上没有 JavaScript。屏幕是一棵固定的树,由您的应用通过编号的动作、字段、插槽、组和开关来驱动。所以有些东西按设计排除在外,各有原因:

  • 状态和 hooks(useState、useEffect、context)。状态由应用持有,并由应用设置屏幕显示的内容。
  • 字段的 value、checked 和 onChange。 应用通过字段的 id 读取和设置它。
  • 展开(spread)的 props。 其中有什么,要到代码运行时才知道。
  • 计算出来的样式、颜色值和全局样式表。 样式是静态的;颜色使用主题颜色,这样大字主题才能为每个屏幕重新配色,对比度也会被检查;而且没有层叠。
  • 动画。
  • 没有上限的列表。 用 .slice(0, 5) 截取它,让屏幕知道最多能显示几行。
  • 除"prop === 字符串"以外的比较,以及屏幕函数中的 if 或 switch。 在应用中算出结果,再作为 prop 传入。
  • 来自软件包的组件,以及屏幕文件夹之外的文件。 屏幕只读取它自己的文件夹及其中的内容:把您的组件放在它旁边,./parts/header。
  • 除了调用一个 prop 还做别的事的处理函数。 onClick={() => props.onSave()} 可以转换;其余的都是应用的工作。

路线图接下来带来什么

当您的代码需要时,覆盖率报告会指出以下计划中的步骤:

  • 更多 CSS 布局:flex 伸展、alignSelf、最小和最大高度、各边的内边距以及外边距;
  • 常见的 HTML 元素,每一种按一条固定规则对应;
  • CSS 模块,每个元素一个类;
  • 分层:彼此叠放的元素;
  • 图片和遮蔽输入。

在某个步骤落地之前,它所涉及的结构会被拒绝,而不是被猜测。每一步都遵守同一条规则:要么精确,要么不做。

读懂错误

错误会给出文件、行和列,一个代码,出了什么问题,以及一行帮助:

web-search.tsx:16:28: error[unknown-name]: `query` is not a prop of the component
 help: text from the application must be a prop: take it as one, function Screen({ query }) { … }

只要有错误,就什么也不会写出。这些代码是:

代码 含义 怎么做
syntax 文件不是有效的 TSX,或违反了每个模块都遵守的规则。 在给出的位置修正代码。
unsupported 子集之外的结构。 按帮助操作:在子集内改写它,或把这项工作移到应用中。
unknown-element 不属于套件、或没有导入的元素。 从 "nowayos:kit" 导入它,或改用套件的元素。
unknown-prop 元素不接受的 prop 或样式属性。 使用表格为它列出的那些。
invalid-value 元素接受的 prop,却给了它不接受的值。 给出表格所列类型的值。
missing-prop 缺少元素必需的 prop。 补上它:表格中以粗体显示这些 prop。
invalid-children 元素包含了它不能包含的内容,例如 <Screen> 中有两个子元素,或 <Column> 中有文本。 把它们包起来,或把文本放进 <Text>。
unknown-name 既不是 prop、设计令牌,也不是导入的名称。 把它作为 prop 接收,或声明它。
duplicate-name 两样东西在生成的代码中会得到同一个名称,例如 isReady 和 is_ready。 重命名其中一个。
reserved-name Rust 或生成的代码为自己保留的名称,例如 type。 重命名它。
limit 超出了大小、深度或数量的限制。 缩短它,或拆分成组件。
no-screen 文件中没有屏幕组件,即返回 <Screen> 的函数。 导出一个。
internal Screen Compiler 自身的缺陷。 附上引发它的输入,报告它。

如果您需要的结构还在路线图上、尚未实现,请附上报告告诉我们:它能显示哪些步骤最重要。