用途
@json-render/solid 是 json-render 的 SolidJS 渲染器,负责把 json-render 规格(Spec)渲染为 Solid 组件树,并保留 Solid 的细粒度响应式(fine-grained reactivity)。目标场景包括:构建 @json-render/solid 的目录(catalog)与注册表(registry)、配置 Renderer 的各类 Provider、实现绑定(bindings)与动作(actions)等。
快速开始
import { Renderer, JSONUIProvider } from "@json-render/solid";
import type { Spec } from "@json-render/solid";
import { registry } from "./registry";
export function App(props: { spec: Spec | null }) {
return (
<JSONUIProvider registry={registry} initialState={{}}>
<Renderer spec={props.spec} registry={registry} />
</JSONUIProvider>
);
}
创建目录(Catalog)
通过 @json-render/core 的 defineCatalog 与 @json-render/solid/schema 的 schema,配合 zod 定义组件与动作:
import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/solid/schema";
import { z } from "zod";
export const catalog = defineCatalog(schema, {
components: {
Button: {
props: z.object({
label: z.string(),
variant: z.enum(["primary", "secondary"]).nullable(),
}),
description: "Clickable button",
},
Card: {
props: z.object({ title: z.string() }),
description: "Card container",
},
},
actions: {
submit: { description: "Submit data" },
},
});
定义组件
组件会从渲染器接收 ComponentRenderProps:
interface ComponentRenderProps<P = Record<string, unknown>> {
element: UIElement<string, P>;
children?: JSX.Element;
emit: (event: string) => void;
on: (event: string) => EventHandle;
bindings?: Record<string, string>;
loading?: boolean;
}
示例:
import type { BaseComponentProps } from "@json-render/solid";
export function Button(props: BaseComponentProps<{ label: string }>) {
return (
<button onClick={() => props.emit("press")}>{props.props.label}</button>
);
}
创建注册表(Registry)
import { defineRegistry } from "@json-render/solid";
import { catalog } from "./catalog";
import { Card } from "./Card";
import { Button } from "./Button";
const { registry, handlers, executeAction } = defineRegistry(catalog, {
components: {
Card,
Button,
},
actions: {
submit: async (params, setState, state) => {
// custom action logic
},
},
});
规格(Spec)结构
{
"root": "card1",
"elements": {
"card1": {
"type": "Card",
"props": { "title": "Hello" },
"children": ["btn1"]
},
"btn1": {
"type": "Button",
"props": { "label": "Click me" },
"on": {
"press": { "action": "submit" }
}
}
}
}
Provider
- StateProvider:状态模型读写,以及通过 store 实现受控模式
- VisibilityProvider:求值 visible 条件
- ValidationProvider:字段校验 + validateForm 集成
- ActionProvider:运行内置与自定义动作
- JSONUIProvider:组合式 Provider 包装器
Hook
- useStateStore、useStateValue、useStateBinding
- useVisibility、useIsVisible
- useActions、useAction
- useValidation、useOptionalValidation、useFieldValidation
- useBoundProp
- useUIStream、useChatUI
内置动作
由 ActionProvider 自动处理:
- setState
- pushState
- removeState
- validateForm
动态属性与绑定
嵌套列表可在外层 repeat 内,通过设置 repeat.statePath 为 { "$item": "field" } 实现。支持的表达式形式包括:
- {"$state": "/path"}
- {"$bindState": "/path"}
- {"$bindItem": "field"}
- {"$template": "Hi ${/user/name}"}
- {"$computed": "fn", "args": {...}}
- {"$cond": <condition>, "$then": <value>, "$else": <value>}
在组件中使用 useBoundProp 处理可写绑定值:
import { useBoundProp } from "@json-render/solid";
function Input(props: BaseComponentProps<{ value?: string }>) {
const [value, setValue] = useBoundProp(
props.props.value,
props.bindings?.value,
);
return (
<input
value={String(value() ?? "")}
onInput={(e) => setValue(e.currentTarget.value)}
/>
);
}
useStateValue、useStateBinding,以及 useFieldValidation 返回的 state / errors / isValid 字段,在 Solid 中均为响应式访问器(reactive accessors)。需在 JSX、createMemo 或 createEffect 中以函数形式调用。
Solid 响应式规则
- 当值需要保持响应式时,不要在函数签名中解构组件 props。
- 将变化的读取保持在 JSX 表达式、createMemo 或 createEffect 内部。
- Context 值通过基于 getter 的对象暴露,使消费方始终观察到实时信号。
流式 UI
import { useUIStream, Renderer } from "@json-render/solid";
const stream = useUIStream({ api: "/api/generate-ui" });
await stream.send("Create a support dashboard");
<Renderer
spec={stream.spec}
registry={registry}
loading={stream.isStreaming}
/>;
聊天 + UI 生成流程可使用 useChatUI。
限制
资料未提供该包的具体版本要求、兼容性范围、性能指标、收费与授权信息,暂未提供。