ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Yao SUI 数据绑定(Data Binding)完全指南:内置变量、JSON 数据配置与后端脚本调用

Yao SUI 数据绑定(Data Binding)完全指南:内置变量、JSON 数据配置与后端脚本调用 Agent 框架后端低代码RAG【免费下载链接】yao✨ All your agents and workspaces in one place, on every device you own. Track tasks on a board, accessible from desktop, mobile, browser, or API. Self-hosted.项目地址https://gitcode.com/gh_mirrors/ya/yao点击查看免费下载导读本文围绕 Yao 引擎内置的 SUISimple User Interface前端框架系统讲解其数据绑定机制从 HTML 模板与.json页面数据配置中可直接使用的内置变量请求数据、URL 信息、上下文环境到$前缀触发 Process 调用、前缀调用后端脚本方法再到BeforeRender与全局数据__data.json的合并优先级。读完本文你将能够在不编写任何 JavaScript 前端代码的前提下用{{ }}模板表达式与 JSON 配置完成页面数据装配、动态渲染与后端逻辑编排。SUI 数据绑定的设计定位SUI 是 Yao App Engine 内置的全栈 Web 开发框架页面由page.html、page.json数据配置、page.backend.ts后端脚本等文件组合而成整体目录结构见 sui/README.md。数据绑定负责把请求数据 页面配置 后端计算三类信息统一注入模板渲染上下文其核心载体是模板表达式{{ ... }}与 JSON 数据配置page.json。从源码看模板表达式基于 expr-lang/exprData.New负责把{{ }}语句编译为表达式程序Data.Exec执行并收集标识符而P_、True、False、Empty四个内置函数正是在编译选项options中注册的见 sui/core/data.go。内置变量Built-in VariablesSUI 为模板和 JSON 配置预置了三组内置变量它们的注入逻辑集中在Request.NewData()中见 sui/core/request.go。请求变量变量说明示例$payloadPOST 请求体{{ $payload.name }}$queryURL 查询参数{{ $query.search }}$param路由参数{{ $param.id }}$cookie请求 Cookie{{ $cookie.session }}对应实现data[$payload] r.Payload、data[$query] r.Query、data[$param] r.ParamsCookie 则通过解析Headers中的Cookie头生成Request.Cookies()见 sui/core/request.go。$query与$header底层是url.Values在 JSON 配置中读取时若命中单值会自动解包为标量见parseArgs中query./header.前缀的特殊处理sui/core/request.go。URL 变量变量说明示例值$url.pathURL 路径/users/123$url.host完整主机含端口example.com:8080$url.domain仅域名example.com$url.scheme协议https$url.url完整 URLhttps://example.com/users实现来自ReqeustURL.Map()sui/core/request.go注意结构体字段URL保存完整地址Host含端口、Domain仅域名、Path为路径、Scheme为协议。上下文变量变量说明示例值$theme当前主题light、dark$locale当前语言区域en-us、zh-cn$timezone系统时区Asia/Shanghai$direction文本方向ltr、rtl$global来自__data.json的全局数据{ title: App }$authOAuth 授权信息当 guard 为oauth时{ user_id: 123 }主题与语言区域是从请求 Cookie 中解析的GetLocale读取localeCookieGetTheme读取color-themeCookie见 sui/core/request.go。$direction在默认文档模板中恒为ltr。$auth仅在请求携带授权信息r.Authorized ! nil时注入若页面启用了oauthguard即可在模板中直接访问授权用户信息。HTML 模板中的使用示例查询参数URL/search?qhellopage2h1Search: {{ $query.q }}/h1 pPage: {{ $query.page ?? 1 }}/p??是表达式语言内置的空值合并运算符当page参数缺失时回退到1。路由参数路由/users/[id]/posts/[postId]URL/users/123/posts/456h1User {{ $param.id }}/h1 pPost {{ $param.postId }}/p路由占位符使用[name]方括号语法SUI 中亦被称为动态路由片段页面链接生成逻辑见 sui/core/page.go其中会依据r.Params把[id]替换为实际值。页面目录可嵌套文件夹名即路由名。POST Payloadform methodPOST input nameemail value{{ $payload.email }} / div s:if{{ $payload.error }}{{ $payload.error }}/div /form$payload直接对应 POST 请求体中的字段配合s:if指令可实现表单提交后的错误回显。主题与语言区域html class{{ $theme }} lang{{ $locale }} body dir{{ $direction }} h1{{ $global.title }}/h1 /body /html这一组合也正是 SUI 默认全局文档模板DocumentDefault的写法见 sui/core/types.go其中还包含{{ $global.title ?? Untitled }}这类带默认值的 title 输出可参照学习。页面数据配置page.jsonpage.json是页面的数据装配中心。其执行入口为Request.Execsui/core/request.go遍历 JSON 的每个键以$开头的键触发 Process/后端脚本调用其余键则逐值解析支持请求变量替换、嵌套数组与对象递归解析见execValuesui/core/request.go。调用结果以去掉$后的名字作为变量名注入渲染数据。静态数据{ title: My Page, items: [ { id: 1, name: Item 1 }, { id: 2, name: Item 2 } ] }静态数据原样注入模板中直接{{ title }}、{{ items }}引用数组/对象默认序列化为 JSON 字符串并标记JSON: true见 sui/core/data.go 的ExecString。Process 调用{ $users: models.user.Get, $settings: { process: models.settings.Find, args: [1] } }两种写法等价字符串简写models.user.Get与对象完整写法processargs。对象形式支持传参args内的$param.xxx、$query.xxx、$payload.xxx、$header.xxx等字符串会被解析为实际请求值见parseArgssui/core/request.go。执行后$users变为users、$settings变为settings供模板使用。使用请求变量{ $user: { process: models.user.Find, args: [$param.id] }, searchQuery: $query.q, currentPath: $url.path }JSON 配置中可用的请求变量$query.name— 查询参数$param.name— 路由参数$payload.name— POST 请求体$header.name— 请求头$url.path/$url.host/$url.domain/$url.scheme注意$header只在 JSON 配置中可用HTML 模板中不可用。这是因为 JSON 值解析路径execValue单独实现了$header.前缀的处理sui/core/request.go而模板表达式环境中仅注入了$payload/$query/$param/$cookie/$url/$theme/$locale/$timezone/$direction/$global/$auth等键Request.NewDatasui/core/request.go。综合示例{ pageTitle: User Profile, userId: $param.id, $user: { process: models.user.Find, args: [$param.id] }, $posts: { process: models.post.Get, args: [ { wheres: [{ column: user_id, value: $param.id }], limit: 10 } ] }, isOwner: $query.edit true }一个综合用法普通键直接绑定请求变量userId、isOwner$键执行两次独立的 Process 调用并共享同一路由参数wheres中的$param.id会在解析参数时被替换为真实值。调用后端脚本方法语法使用MethodName语法可以调用页面page.backend.ts文件中定义的函数{ $record: GetRecord, $items: { process: GetItems, args: [active, 20] } }重要Request 对象会自动作为最后一个参数追加到后端函数中。page.backend.ts// Called from .json as: $record: GetRecord // Receives: (request) function GetRecord(request: Request): any { const id request.params.id; // Access route params via request return Process(models.record.Find, id); } // Called from .json as: { process: GetItems, args: [active, 20] } // Receives: (active, 20, request) function GetItems(status: string, limit: number, request: Request): any[] { return Process(models.item.Get, { wheres: [{ column: status, value: status }], limit: limit, }); }源码实现印证Request.call检测到process名以开头时会取出后的方法名并调用r.Script.Call(r, method, processArgs...)sui/core/request.go而Script.Call在最后一行args append(args, r)把 Request 作为末位参数传入 V8 上下文执行sui/core/script.go。后端脚本文件优先加载*.backend.ts不存在时回退*.backend.js见 sui/core/script.go。⚠️ 常见错误不能在后端脚本中直接使用$param.id。$param、$query等变量仅在 HTML 模板与.json配置中可用在后端脚本中必须通过request参数访问request.params.id、request.query.search等。内置函数Built-in Functions四个内置函数的真实实现位于 sui/core/data.go均在模板编译选项中注册因此可直接用于任何{{ }}表达式。P_() — Process 调用在模板中直接调用 Yao Process!-- Simple call -- span{{ P_(utils.formatDate, createdAt) }}/span !-- With multiple arguments -- span{{ P_(utils.calculate, price, quantity, discount) }}/span !-- In conditions -- div s:if{{ P_(auth.hasPermission, admin) }}Admin Panel/div实现_process取出第一个字符串参数作为 Process 名其余参数作为调用参数执行process.Exec()并返回结果sui/core/data.go。True() / False()布尔值判断div s:if{{ True(user) }}User exists/div div s:if{{ False(error) }}No error/div !-- Equivalent to -- div s:if{{ user ! null user ! false user ! 0 }}User exists/div实现细节_true布尔值原样返回字符串转为小写后非false与0即视为真整型! 0为真无参数或其它类型返回 falsesui/core/data.go。Empty()判断数组或对象是否为空div s:if{{ Empty(items) }}No items/div div s:if{{ !Empty(items) }}{{ items.length }} items found/div !-- Works with objects too -- div s:if{{ Empty(settings) }}No settings configured/div实现细节_empty对nil、空字符串、0、false及各类空 map/切片包括map[string]interface{}、[]interface{}、Data等均返回 truesui/core/data.go。全局数据__data.json全局数据对所有页面可见通过$global变量访问。文件位于模板根目录/templates/template/__data.json{ title: My Application, version: 1.0.0, company: { name: ACME Inc, email: contactacme.com }, navigation: [ { label: Home, href: / }, { label: About, href: /about } ] }模板中访问title{{ $global.title }}/title footer© {{ $global.company.name }}/footer nav a s:for{{ $global.navigation }} s:for-itemitem href{{ item.href }} {{ item.label }} /a /nav实现层面Page.Exec先执行全局数据request.ExecString(string(page.GlobalData))再执行页面数据最后把全局结果统一放入data[$global]sui/core/page.go。s:for为模板循环指令配合s:for-item声明循环变量。后端脚本数据BeforeRenderpage.backend.ts中导出的BeforeRender(request)函数会在渲染前执行返回的数据与页面数据合并page.backend.tsfunction BeforeRender(request: Request): Recordstring, any { return { user: Process(session.Get, user), notifications: Process(models.notification.Get, { wheres: [{ column: read, value: false }], limit: 5, }), serverTime: new Date().toISOString(), }; }page.htmldiv s:if{{ user }} Welcome, {{ user.name }}! span s:if{{ !Empty(notifications) }} {{ notifications.length }} new notifications /span /div footerServer time: {{ serverTime }}/footer实现Script.BeforeRender通过 V8 上下文调用BeforeRender(request, props)要求返回值是Recordstring, anymap否则报错见 sui/core/script.go。BeforeRender适合承载依赖会话、实时计算的动态数据如登录用户、未读通知、服务器时间。数据优先级Data Priority同一键名存在于多个数据源时按以下优先级覆盖BeforeRender最高— 后端脚本数据page.json— 页面数据配置__data.json最低— 全局数据// BeforeRender returns { title: From Backend } // page.json has { title: From JSON } // __data.json has { title: Global Title } // Result: title From Backend这与Page.Exec的执行顺序一致全局数据先被解析并放进$global页面 JSON 数据随后解析为顶层键最终由BeforeRender的返回值覆盖同名键——全局数据始终以$global.key形式访问因此实际上页面层BeforeRenderpage.json天然优先于全局层。实战小结模板表达式{{ }}支持内置变量、??默认值、比较运算与P_/True/False/Empty四个函数由 sui/core/data.go 中的 expr 引擎统一编译执行page.json是数据装配核心$键触发 Process 或后端脚本调用普通键支持$query./$param./$payload./$header./$url.请求变量引用$header仅在 JSON 配置可用后端脚本通过request参数访问请求上下文Request 恒为函数末位参数BeforeRender用于渲染前动态注入数据优先级最高全局数据__data.json通过$global为所有页面提供站点级配置品牌信息、导航、SEO 默认值等。如需继续深入可参考 SUI 模板语法、后端脚本 与 组件体系 等配套文档构建完整页面。赞分享Agent 框架后端低代码RAG【免费下载链接】yao✨ All your agents and workspaces in one place, on every device you own. Track tasks on a board, accessible from desktop, mobile, browser, or API. Self-hosted.项目地址https://gitcode.com/gh_mirrors/ya/yao点击查看免费下载相关推荐Yao SUI 后端脚本Backend Scripts完全指南服务端逻辑、数据绑定与 API 端点开发实战Yao SUI 后端脚本Backend Scripts完全指南服务端逻辑、数据绑定与 API 端点开发实战 SUISimple User InterfaAgent 框架后端低代码RAGWinUtil终极指南一键批量安装软件与Windows系统优化神器WinUtil终极指南一键批量安装软件与Windows系统优化神器 你是否厌倦了每次重装Windows系统后繁琐的软件安装过程是否被复杂的系统优化设置搞得头桌面应用运维终极指南如何使用Realm数据库实现Android双向数据绑定终极指南如何使用Realm数据库实现Android双向数据绑定 Realm数据库是一个功能强大的移动端数据库解决方案而Data Binding则是Andro数据库移动开发嵌入式数据库上一篇TTTAttributedLabel内存泄漏分析Instruments调试实践下一篇Ultimate Vocal Remover实操安装指南本地人声伴奏分离创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表