Constela:实现 React/Next.js 级别的表达力,涵盖计时器、表单、门户等
I’m happy to translate the article for you, but I need the full text of the post. Could you please paste the content you’d like translated (excluding the source line you’ve already provided)? Once I have the article’s text, I’ll translate it into Simplified Chinese while preserving all formatting, code blocks, URLs, and the source link at the top.
什么是 Constela?
Constela 是一种编译器优先的 UI 语言,针对 AI 生成的界面进行了优化。与其编写 JavaScript,不如在受限的 JSON DSL 中描述 UI 行为,该 DSL 会被验证、分析并编译成最小化的运行时代码。通过最新发布,Constela 在大多数常见用例中已实现与 React/Next.js 的功能等价。
计时器操作
delay
在指定的延迟后执行步骤。
{
"name": "showNotification",
"steps": [
{
"do": "set",
"target": "notification",
"value": { "expr": "lit", "value": "Saved!" }
},
{
"do": "delay",
"ms": { "expr": "lit", "value": 3000 },
"then": [
{
"do": "set",
"target": "notification",
"value": { "expr": "lit", "value": "" }
}
]
}
]
}
interval
以指定的间隔重复执行一个动作。计时器 ID 会存储在 result 中。
{
"name": "startPolling",
"steps": [
{
"do": "interval",
"ms": { "expr": "lit", "value": 5000 },
"action": "fetchLatestData",
"result": "pollingTimerId"
}
]
}
clearTimer
通过其 ID 停止正在运行的计时器。
{
"name": "stopPolling",
"steps": [
{
"do": "clearTimer",
"target": { "expr": "state", "name": "pollingTimerId" }
}
]
}
Source: …
扩展事件数据
事件处理程序现在可以访问丰富的事件数据。
| 事件类型 | 可用变量 |
|---|---|
| Input | value, checked |
| Keyboard | key, code, ctrlKey, shiftKey, altKey, metaKey |
| Mouse | clientX, clientY, pageX, pageY, button |
| Touch | touches(clientX, clientY, pageX, pageY 的数组) |
| Scroll | scrollTop, scrollLeft |
| File Input | files(name, size, type 的数组) |
键盘快捷键示例
{
"onKeyDown": {
"event": "keydown",
"action": "handleShortcut",
"payload": {
"key": { "expr": "var", "name": "key" },
"isCtrl": { "expr": "var", "name": "ctrlKey" }
}
}
}
文件输入示例
{
"kind": "element",
"tag": "input",
"props": {
"type": { "expr": "lit", "value": "file" },
"multiple": { "expr": "lit", "value": true },
"onChange": {
"event": "change",
"action": "handleFiles",
"payload": { "expr": "var", "name": "files" }
}
}
}
表单特性
编程式焦点控制
// Focus an element
{ "do": "focus", "target": { "expr": "ref", "name": "emailInput" }, "operation": "focus" }
// Select text
{ "do": "focus", "target": { "expr": "ref", "name": "codeInput" }, "operation": "select" }
// Blur (unfocus)
{ "do": "focus", "target": { "expr": "ref", "name": "searchInput" }, "operation": "blur" }
验证状态 (HTML5 约束验证 API)
{
"kind": "element",
"tag": "input",
"ref": "emailInput",
"props": {
"type": { "expr": "lit", "value": "email" },
"required": { "expr": "lit", "value": true }
}
}
显示验证错误:
{
"kind": "if",
"condition": {
"expr": "not",
"operand": {
"expr": "validity",
"ref": "emailInput",
"property": "valid"
}
},
"then": {
"kind": "text",
"value": {
"expr": "validity",
"ref": "emailInput",
"property": "message"
}
}
}
可用的有效性属性
valid– 整体有效性valueMissing– 必填字段为空typeMismatch– 类型不匹配(email、url 等)patternMismatch– 模式不匹配tooLong/tooShort– 长度约束违规rangeUnderflow/rangeOverflow– 范围约束违规message– 浏览器的验证信息
门户 & 观察者
门户
将内容渲染到 DOM 中的其他位置(例如模态框、工具提示)。
{
"kind": "portal",
"target": "body",
"children": [
{
"kind": "element",
"tag": "div",
"props": { "className": { "expr": "lit", "value": "modal-overlay" } },
"children": [
{
"kind": "element",
"tag": "div",
"props": { "className": { "expr": "lit", "value": "modal-content" } },
"children": [ /* modal content */ ]
}
]
}
]
}
目标选项
"body"–document.body"head"–document.head- 任意 CSS 选择器(例如
"#modal-root")
IntersectionObserver(无限滚动)
{
"kind": "element",
"tag": "div",
"ref": "sentinel",
"props": {
"onIntersect": {
"event": "intersect",
"action": "loadMoreItems",
"options": {
"threshold": 0.5,
"rootMargin": "100px"
}
}
}
}
防抖 & 节流
控制事件处理函数的执行频率。
防抖(在最后一次事件后 300 毫秒执行)
{
"onInput": {
"event": "input",
"action": "search",
"debounce": 300
}
}
节流(每 100 毫秒最多执行一次)
{
"onScroll": {
"event": "scroll",
"action": "trackScroll",
"throttle": 100
}
}
常见 UI 模式
| Pattern | Constela Feature |
|---|---|
| 自动隐藏通知 | delay step |
| 实时数据轮询 | interval + clearTimer |
| 键盘快捷键 | Extended keyboard event data |
| 文件上传界面 | files event data |
| 表单验证 | validity expression |
| 模态对话框 | portal node |
| 无限滚动 | intersect event |
| 输入即搜索 | debounce option |
入门指南
npm install @constela/start
mkdir -p src/routes
echo '{"version":"1.0","state":{},"actions":[],"view":{"kind":"element","tag":"div","children":[{"kind":"text","value":{"expr":"lit","value":"Hello Constela!"}}]}}' > src/routes/index.json
npx constela dev
资源
- GitHub Repository: https://github.com/constela/constela
- Official Website: https://constela.dev