SuperAPI AI 工具集

solid

前端与建站

查看项目

更新于 10-16 07:30

技能介绍

用途

@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。

限制

资料未提供该包的具体版本要求、兼容性范围、性能指标、收费与授权信息,暂未提供。