ARTICLE DETAIL

资讯详情

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

NocoBase 客户端上下文常用能力完全指南:ctx.api、ctx.t、ctx.logger、ctx.router、ctx.viewer 与 ctx.acl 实战详解

NocoBase 客户端上下文常用能力完全指南:ctx.api、ctx.t、ctx.logger、ctx.router、ctx.viewer 与 ctx.acl 实战详解 NocoBase 客户端上下文常用能力完全指南ctx.api、ctx.t、ctx.logger、ctx.router、ctx.viewer 与 ctx.acl 实战详解【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase导读在 NocoBase 插件开发中上下文Context对象是连接插件代码与平台内置能力的桥梁。本文围绕FlowEngineContext展开系统讲解客户端上下文中的常用能力——API 请求ctx.api、国际化ctx.t/ctx.i18n、结构化日志ctx.logger、路由注册与导航ctx.router/ctx.route/ctx.location、视图管理ctx.viewer/ctx.view以及 FlowModel 注册this.flowEngine。读完本文你将掌握在 Plugin 与 React 组件两种场景下正确使用这些能力、规避同名属性混淆并具备独立开发带请求、多语言、日志、弹窗与页面路由的自定义插件的能力。上下文能力总览Plugin 与 Component 的异同NocoBase 的上下文有两个访问入口但指向的是同一个对象FlowEngineContext实例Plugin 里通过this.context访问Plugin 类还提供了一批快捷属性见 Plugin 插件React 组件里通过useFlowContext()获取从nocobase/flow-engine导入。在源码层面useFlowContext定义于 FlowContextProvider.tsx其实现只是useContext(FlowReactContext)而FlowReactContext由FlowContextProvider注入FlowContext实例FlowEngineContext类则定义于 flowContext.ts继承自BaseFlowEngineContext通过defineProperty/defineMethod动态挂载api、logger、viewer、route、location、t、engine等成员。这也是为什么ctx.xxx的成员可以用ctx.defineProperty()/ctx.defineMethod()动态扩展。不过有些能力只在 Plugin 里可用有些只在组件里可用有些两边都有但写法不同。先看总览表能力Pluginthis.xxxComponentctx.xxx说明API 请求this.context.apictx.api用法一致国际化this.t()/this.context.tctx.tthis.t()自动注入插件 namespace日志this.context.loggerctx.logger用法一致路由注册this.router.add()-仅 Plugin页面导航-ctx.router.navigate()仅组件路由信息this.context.locationctx.route/ctx.location建议在组件中使用视图管理this.context.viewerctx.viewer打开弹窗 / 抽屉等FlowEnginethis.flowEngine-仅 Plugin最容易混淆的是this.router与ctx.routerthis.router是 Plugin 类暴露的 RouterManager用于注册路由.add()而ctx.router是上下文上的 React Router 实例用于页面导航.navigate()。该区分在 Plugin 类源码中也能看到——Plugin.ts 中this.router来自this.app.router而ctx.router则声明于 flowContext.ts 的类型declare router: Router。下面按能力逐项介绍。API 请求ctx.api通过ctx.api.request()调用后端接口用法与 Axios 一致底层即 Axios 实例。ctx.api的类型是APIClient定义于nocobase/sdk其核心实现见 APIClient.ts支持url、method、data、params、headers等标准请求选项。在 Plugin 中使用在插件的load()等生命周期方法里通过this.context.api直接发请求import { Plugin } from nocobase/client-v2; class MyPlugin extends Plugin { async load() { // 在 load() 里直接发请求 const response await this.context.api.request({ url: app:getInfo, method: get, }); console.log(应用信息, response.data); } }在组件中使用在组件中通过useFlowContext()拿到ctx后即可发起 GET / POST 等请求import { useFlowContext } from nocobase/flow-engine; export default function MyPage() { const ctx useFlowContext(); const handleLoad async () { // GET 请求 const response await ctx.api.request({ url: users:list, method: get, }); console.log(response.data); // POST 请求 await ctx.api.request({ url: users:create, method: post, data: { name: Tao Tao }, }); }; return button onClick{handleLoad}加载数据/button; }提示NocoBase 的 RESTful 资源接口采用资源名:操作名的命名如users:list、users:create、posts:list。资源接口的详细使用见 资源与请求。搭配 ahooks useRequest在组件中可以搭配ahooks的useRequest简化请求的状态管理loading / error / refresh 等import { useFlowContext } from nocobase/flow-engine; import { useRequest } from ahooks; export default function PostList() { const ctx useFlowContext(); const { data, loading, error, refresh } useRequest(() ctx.api.request({ url: posts:list, method: get, }), ); if (loading) return div加载中.../div; if (error) return div请求出错: {error.message}/div; return ( div button onClick{refresh}刷新/button pre{JSON.stringify(data?.data, null, 2)}/pre /div ); }请求拦截器ctx.api.axios暴露了底层 Axios 实例可以添加请求 / 响应拦截器通常放在 Plugin 的load()中设置async load() { // 请求拦截器添加自定义请求头 this.context.api.axios.interceptors.request.use((config) { config.headers[X-Custom-Header] my-value; return config; }); // 响应拦截器统一错误处理 this.context.api.axios.interceptors.response.use( (response) response, (error) { console.error(请求出错, error); return Promise.reject(error); }, ); }从源码看APIClient 自身的拦截器在 APIClient.ts 中注册认证信息如X-Locale、X-Role由 Auth 中间件在请求发起前注入见 Auth.ts。你在load()里追加的拦截器会在此之后执行因此可以安全地叠加自定义逻辑。NocoBase 自定义请求头NocoBase Server 支持以下自定义请求头通常由拦截器自动注入不需要手动设置Header说明X-App多应用场景下指定当前访问的应用X-Locale当前语言比如zh-CN、en-USX-Hostname客户端主机名X-Timezone客户端所在时区比如08:00X-Role当前角色X-Authenticator当前用户认证方式X-Locale与X-Role的注入可在 Auth.ts 中看到实现依据X-App主要用于多应用multi-app场景下区分目标应用。国际化ctx.t / ctx.i18nNocoBase 插件通过src/locale/目录管理多语言文件通过ctx.t()在代码中使用翻译。多语言文件在插件的src/locale/下按语言创建 JSON 文件plugin-hello/ └── src/ └── locale/ ├── zh-CN.json └── en-US.json// zh-CN.json { Hello: 你好, Your name is {{name}}: 你的名字是 {{name}} }// en-US.json { Hello: Hello, Your name is {{name}}: Your name is {{name}} }:::warning 注意初次添加语言文件需要重启应用才能生效。:::ctx.t()在组件中通过ctx.t()获取翻译文本const ctx useFlowContext(); // 基本用法 ctx.t(Hello); // 带变量 ctx.t(Your name is {{name}}, { name: NocoBase }); // 指定命名空间默认命名空间是插件的包名 ctx.t(Hello, { ns: my-project/plugin-hello });this.t()在 Plugin 里用this.t()更方便——它会自动把插件的包名注入为 namespace不需要手动传nsclass MyPlugin extends Plugin { async load() { // 自动使用当前插件的包名作为 ns console.log(this.t(Hello)); // 等同于 console.log(this.context.t(Hello, { ns: my-project/plugin-hello })); } }源码依据Plugin.t()在 Plugin.ts 中实现为this.app.i18n.t(text, { ns: this.options?.packageName, ...options })即自动注入packageName作为命名空间而ctx.t则通过FlowI18n实例翻译见 flowContext.ts。ctx.i18nctx.i18n是底层的 i18next 实例通常直接用ctx.t()就够了。如果需要动态切换语言、监听语言变化等可以用ctx.i18n// 获取当前语言 const currentLang ctx.i18n.language; // zh-CN // 监听语言变化 ctx.i18n.on(languageChanged, (lng) { console.log(语言切换为, lng); });上下文还提供了ctx.locale属性用于获取当前语言this.api?.auth?.locale || this.i18n?.language见 flowContext.ts。tExpr()tExpr()用于生成延迟翻译的表达式字符串通常在FlowModel.define()里使用——因为 define 是在模块加载时执行的此时还没有 i18n 实例import { tExpr } from nocobase/flow-engine; HelloBlockModel.define({ label: tExpr(Hello block), // 生成 {{t(Hello block)}}运行时再翻译 });更完整的国际化用法翻译文件写法、useT hook、tExpr 等见 i18n 国际化。NocoBase 支持的语言代码完整列表含zh-CN、en-US、de-DE、ja-JP等数十种遵循 IETF BCP 47 规范见 语言列表。日志ctx.logger通过ctx.logger输出结构化日志基于 pino。ctx.logger的类型为pino.Logger见 flowContext.ts因此支持 pino 的占位符、绑定字段等完整能力。在 Plugin 中使用import { Plugin } from nocobase/client-v2; class MyPlugin extends Plugin { async load() { this.context.logger.info(插件加载完成, { plugin: my-plugin }); this.context.logger.error(初始化失败, { error }); } }在组件中使用import { useFlowContext } from nocobase/flow-engine; export default function MyPage() { const ctx useFlowContext(); const handleLoad async () { ctx.logger.info(页面加载完成, { page: UserList }); ctx.logger.debug(当前用户状态, { user }); }; // ... }日志级别从高到低fatalerrorwarninfodebugtrace。只有大于或等于当前配置级别的日志才会输出。该行为在 FlowEngine 的测试中也有体现——flowEngine.removeModel.test.ts 验证了生产环境下 logger 级别默认降为warn此时debug日志不再输出。客户端与服务端日志体系的更多细节见 日志logger。路由ctx.router / ctx.route / ctx.location路由相关能力分为三部分注册仅 Plugin、导航和信息获取仅组件。路由注册this.router / this.pluginSettingsManager在 Plugin 的load()中通过this.router.add()注册页面路由通过this.pluginSettingsManager注册插件设置页async load() { // 注册普通页面路由 this.router.add(hello, { path: /hello, componentLoader: () import(./pages/HelloPage), }); // 注册插件设置页会出现在「插件配置」菜单里 this.pluginSettingsManager.addMenuItem({ key: my-settings, title: this.t(My Settings), icon: SettingOutlined, // Ant Design 图标 }); this.pluginSettingsManager.addPageTabItem({ menuKey: my-settings, key: index, title: this.t(My Settings), componentLoader: () import(./pages/MySettingsPage), }); }详细用法见 Router 路由。完整的设置页示例见 做一个插件设置页。:::warning 注意this.router是 RouterManager用于注册路由。this.pluginSettingsManager是 PluginSettingsManager用于注册设置页。两者跟组件里的ctx.routerReact Router用于页面导航不是同一个东西。:::页面导航ctx.router在组件中通过ctx.router.navigate()进行页面跳转const ctx useFlowContext(); ctx.router.navigate(/hello); // - /v/hello路由信息ctx.route在组件中通过ctx.route获取当前路由信息const ctx useFlowContext(); // 获取动态参数比如路由定义为 /users/:id const { id } ctx.route.params; // 获取路由名字 const { name } ctx.route;ctx.route的完整类型与源码中 flowContext.ts 的RouteOptions一致interface RouteOptions { name?: string; // 路由唯一标识 path?: string; // 路由模板 pathname?: string; // 路由的完整路径 params?: Recordstring, any; // 路由参数 }当前 URLctx.locationctx.location提供当前 URL 的详细信息类似浏览器的window.location类型为 react-router 的Locationconst ctx useFlowContext(); console.log(ctx.location.pathname); // /v/hello console.log(ctx.location.search); // ?page1 console.log(ctx.location.hash); // #sectionctx.route和ctx.location虽然在 Plugin 里也能通过this.context访问到不过插件加载时的 URL 是不确定的拿到的值没有意义。建议在组件中使用。视图管理ctx.viewer / ctx.viewctx.viewer提供了命令式打开弹窗、抽屉等视图的能力源码类型为FlowViewer见 flowContext.ts。在 Plugin 和组件中都可以用。在 Plugin 中使用import { Plugin } from nocobase/client-v2; class MyPlugin extends Plugin { async load() { // 比如在某个初始化逻辑中打开一个弹窗 this.context.viewer.dialog({ title: 欢迎, content: () div插件初始化完成/div, }); } }在组件中使用import { Button } from antd; import { useFlowContext } from nocobase/flow-engine; export default function MyPage() { const ctx useFlowContext(); const openDetail () { // 打开弹窗 ctx.viewer.dialog({ title: 编辑用户, content: () UserEditForm /, }); }; const openDrawer () { // 打开抽屉 ctx.viewer.drawer({ title: 详情, content: () UserDetail /, }); }; return ( div Button onClick{openDetail}编辑/Button Button onClick{openDrawer}查看详情/Button /div ); }通用方法// 通过 type 指定视图类型 ctx.viewer.open({ type: dialog, // dialog | drawer | popover | embed title: 标题, content: () SomeComponent /, });在 FlowEngine 的视图相关测试中如 flowSettings.open.test.tsxviewer通过ctx.defineProperty(viewer, { value: { dialog, drawer, ... } })注入上下文并断言drawer/dialog被正确调用可作为viewer行为与调用约定的测试佐证。在视图内部操作ctx.view在弹窗/抽屉内部的组件中可以通过ctx.view来操作当前视图比如关闭import { Button } from antd; import { useFlowContext } from nocobase/flow-engine; function DialogContent() { const ctx useFlowContext(); return ( div p弹窗内容/p Button onClick{() ctx.view.close()}关闭/Button /div ); }ctx.view是当前已挂载视图的引用FlowView。与之配套useFlowViewer()可获取用于打开新视图的FlowVieweruseFlowView()获取当前视图见 FlowContextProvider.tsx。FlowEnginethis.flowEnginethis.flowEngine是 FlowEngine 实例仅在 Plugin 中可用Plugin.ts 中get flowEngine()返回this.app.flowEngine。通常用它来注册 FlowModelimport { Plugin } from nocobase/client-v2; class MyPlugin extends Plugin { async load() { // 注册 FlowModel推荐按需加载写法 this.flowEngine.registerModelLoaders({ HelloBlockModel: { loader: () import(./models/HelloBlockModel), }, }); } }FlowModel 是 NocoBase 可视化配置体系的核心——如果你的组件需要出现在「添加区块 / 字段 / 操作」菜单里就需要通过 FlowModel 来包装。FlowModel 与 FlowEngine 的详细用法见 FlowEngine客户端 与 FlowEngine 完整文档。此外ctx上也暴露了ctx.engineFlowEngine 实例与ctx.getModel(name)等方法flowContext.ts。更多能力以下能力在更高级的场景中可能用到简要列出属性说明ctx.model当前 FlowModel 实例在 Flow 执行上下文中可用ctx.ref组件引用搭配ctx.onRefReady使用ctx.exit()退出当前 Flow 的执行ctx.defineProperty()向上下文动态添加自定义属性ctx.defineMethod()向上下文动态添加自定义方法ctx.useResource()获取数据资源操作接口ctx.dataSourceManager数据源管理其中ctx.defineProperty()与ctx.defineMethod()是 FlowContext 动态扩展机制的核心实现见 flowContext.tsFlowEngine 自身的大量能力如api、viewer、t、runjs、request都是通过这两个方法挂载到上下文上的你自定义的属性也会出现在变量选择器 / RunJS 环境中。这些能力的详细用法可以参考 FlowEngine 完整文档。相关链接Context 上下文概述 — 两种上下文入口的异同Plugin 插件 — Plugin 快捷属性Component 组件开发 — useFlowContext 在组件中的用法Router 路由 — 路由注册和导航FlowEngine 完整文档 — 完整的 FlowEngine 参考i18n 国际化 — 翻译文件写法、tExpr、useT语言列表 — NocoBase 支持的语言代码做一个插件设置页 — ctx.api 的完整使用示例FlowEngine客户端 — FlowModel 基础用法【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表