Constela:实现 React/Next.js 级别的表达力,涵盖计时器、表单、门户等

发布: (2026年1月18日 GMT+8 10:52)
5 min read
原文: Dev.to

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:

扩展事件数据

事件处理程序现在可以访问丰富的事件数据。

事件类型可用变量
Inputvalue, checked
Keyboardkey, code, ctrlKey, shiftKey, altKey, metaKey
MouseclientX, clientY, pageX, pageY, button
TouchtouchesclientX, clientY, pageX, pageY 的数组)
ScrollscrollTop, scrollLeft
File Inputfilesname, 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 模式

PatternConstela 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

资源

Back to Blog

相关文章

阅读更多 »

SEO + RAO + Access = 潜在客户

SEO:被认知——SEO仍然重要;它不再主要是为了获取点击,而是更在于将你的网站定位为: - 事实来源 - 参考点 - …

人类、机器和Ratatouille 🐀

引言 对AI系统中系统复杂性的务实响应 长期以来,我们设计数字产品的方式就像许多人想象厨房的运作方式一样: