跳到主要内容

全代码页面开发

在真实业务交付中,并不总能覆盖复杂交互与高度个性化的场景:组件行为难以完全自定义、依赖与版本受限、团队既有前端资产难以复用,调试与性能优化也常被框架边界所束缚。为解决这些痛点,我们推出“全代码页面”能力,让你以原生前端的方式开发页面,同时无缝对接平台能力加速交付。你可以使用熟悉的 React 或 Vue(完整生命周期)自由组织代码,通过网络导包或配置第三方依赖掌控技术栈,并直接使用平台提供的数据模型读写与后端服务调用;在不牺牲自由度的前提下,获得统一鉴权、上下文与运维支撑,让复杂页面既能做得出来,也能长期稳定维护和快速演进。

React 全代码页面

平台使用React构建,React全代码页面能最大程度与平台融合。

创建 React 全代码页面

React全代码页面创建

在元素目录树点击搜索框右侧的+按钮,选择页面-全代码页面。随后弹出创建全代码页面元素的弹窗。

React全代码页面创建弹窗

创建弹窗中只需填写名称即可,点击确定完成创建。

默认全代码页面

创建完成后会在左侧元素树中显示。默认全代码页面有一个可点击的按钮,按钮点击后弹出so cool!!!,初始文件如下图:

全代码的代码

默认生成两个文件:一个 index.tsx,一个 e.jsone.json 是页面元素的定义;重点关注 index.tsxindex.tsx 会导出两个核心模块:Render 函数(当前全代码页面的主渲染函数)和 PageCls(一个页面类,继承自 BasePage)。PageCls 会在页面渲染前由系统进行实例化,并传入到 Render 的 props 中。

PageCls 继承自 BasePage。关于 BasePage,参考基础页面

使用样式

在全代码页面中,你可以按需选择样式方案:内联样式(CSS inline)、CSS‑in‑JS、CSS 开箱即用,无需额外的打包配置;而采用原生 LESS 或 SCSS 时,需要在项目中启用对应的打包配置后方可生效。

样式

LESS 和 SCSS 的样式文件需要配置解析插件,参考引入打包插件

// 内联样式示例 - 直接在JSX中定义样式
<div style={{color: "red"}}>hello world - 内联样式</div>
提示

使用 CSS‑in‑JS 时,可直接消费 antd 的主题 token,与平台默认样式自然对齐;同时也能读取并复用你在平台的“全局样式”中定义的自定义变量,实现品牌色、圆角、阴影等统一管理与一处生效。参考《全局样式》。

使用本地资源

平台提供了常用资源的解析能力,全代码中可以直接使用import语句将资源引入,以图片为例。

import logo from './logo.png';

export const Render = () =>{
return <img src={logo} alt="logo" />
}

更多资源的解析能力,请查看默认loader映射,你也可以通过打包配置的使用来扩展loader映射。

使用 Ant Design 的组件

平台基于 React 框架,内置了 Ant Design UI 组件库,可以直接使用所有 Ant Design 组件;移动端可使用 Ant Design Mobile 组件库。

import { Button } from 'antd';

export const Render = () =>{
return <Button>按钮</Button />
}

更多内置包,请查看系统内置包一览表

内嵌已有标准页面

在全代码页面中复用已有的标准页面,可以减少重复开发,提高代码复用性。下图展示了全代码页面与内嵌标准页面的交互示例。

全代码页面内嵌页面

示例演示了跨页面组件交互:全代码页面的按钮控制内嵌页面表格的数据刷新,同时监听表格行点击事件,获取并显示当前行的ID信息。

实现如下:

import { useRef } from "react";
import { Button, message } from "antd";
import { Jit } from "jit";
import { ElementRender } from "jit-widgets";

// 全代码的实现包括:渲染器和逻辑处理类
// Render是页面的渲染器,UI部分在这里实现,它是一个React组件
const Render = (props) => {
const embeddedPageRef = useRef(null);

// 刷新内嵌页面的表格
const handleRefreshTable = () => {
if (embeddedPageRef.current?.Table1) {
embeddedPageRef.current.Table1.call();
}
};

// 绑定内嵌页面实例和事件
const handlePageInit = (pageInstance) => {
embeddedPageRef.current = pageInstance;

// 绑定表格行点击事件
pageInstance.Table1?.subscribeEvent("clickRow", () => {
const activeRowId = pageInstance.Table1.activeRow?.id?.value;
message.info(`表格行被点击,ID:${activeRowId}`);
});
};

return (
<div>
<Button type="primary" onClick={handleRefreshTable}>
刷新表格
</Button>
<h3>下面是内嵌页面;点击上面的按钮与表格交互,点击表格可触发绑定事件。</h3>
<ElementRender
elementPath="pages.embeddedPages"
onInitAfter={handlePageInit}
/>
</div>
);
};
// 这是全代码页面逻辑处理类,逻辑部分在这里实现,它是一个 JavaScript 的 class
class PageCls extends Jit.BasePage {
// 可以在这里添加页面特有的方法
}

export { Render, PageCls };

ElementRender 除了渲染标准页面元素,还可以渲染其他全代码页面,只需将对应元素的 fullName 配置到 elementPath 属性。若需要与内嵌页面交互,可配置 onInitAfter 属性;初始化完成后会将内嵌页面的 page 实例作为参数传递。内嵌页面的 page 实例示例如下:

import type { ComponentPageScheme } from "jit";
import { Jit } from "jit";
import schemeJson from "./scheme.json";
type BaseComponent = InstanceType<typeof Jit.BaseComponent>;

class PageCls extends Jit.GridPage {
Table1!: BaseComponent;
scheme: ComponentPageScheme = schemeJson;
bindEvent() {}
}

export default PageCls;

内嵌页面包含一个名为 Table1 的表格实例,全代码页面可以通过该页面的实例对其进行操作。

使用标准组件

在全代码页面中复用已有的标准组件,可以减少重复开发,提高代码复用性。下图展示了全代码页面与标准组件的交互示例。

全代码页面标准组件

示例演示了跨页面组件交互:全代码页面的按钮控制表格组件的数据刷新,同时监听表格行点击事件,获取并显示当前行的ID信息。

所有标准组件都是由配置驱动渲染,组件的渲染器接受一个组件实例,实例通过配置进行构造。因为组件的配置复杂,在全代码中使用标准组件时,建议开发者先创建标准页面,在标准页面添加标准组件,并配置好组件,再复制组件的配置到全代码页面中。

复制表格配置

点击要复制组件的页面,切换到源码模式,打开scheme.json找到componentList配置项,将要使用的组件配置复制到全代码页面即可。

示例代码如下:

import { Button, message } from 'antd';
import { Jit } from 'jit';

import ComponentRender from './ComponentRender';
import tableConfig from './tableConfig.json';

// 全代码的实现包括:渲染器和逻辑处理类
// Render是页面的渲染器,UI部分在这里实现,它是一个React组件
const Render = (props) => {
// 页面渲染器接收一个page参数,page是页面逻辑处理类的示例对象
const page = props.page;

// 刷新内嵌页面的表格
const handleRefreshTable = () => {
if (page[tableConfig.name]) {
page[tableConfig.name].call();
}
};

const handleComponentReady = (compIns: any) => {
compIns.subscribeEvent('clickRow', () => {
const activeRowId = compIns.activeRow?.id?.value;
message.info(`表格行被点击,ID:${activeRowId}`);
});
};

return (
<div>
<Button type="primary" onClick={handleRefreshTable}>
刷新表格
</Button>
<h3>下面是标准组件,点击上面的按钮和表格交互</h3>
<ComponentRender config={tableConfig} page={page} onReady={handleComponentReady} />
</div>
);
};

// 这是全代码页面逻辑处理类,逻辑部分在这里实现,它是一个 JavaScript 的 class
class PageCls extends Jit.BasePage {}

export { Render, PageCls };

index.tsx - 主页面组件,实现 UI 渲染和事件交互逻辑。

ComponentRender.tsx - 可复用的标准组件渲染器,负责动态加载和实例化标准组件。

tableConfig.json - 表格组件配置示例,包含数据模型引用 models.cascadeTableData,实际使用需替换为项目中的真实数据模型。

e.json - 页面元素定义文件,type 为 "pages.NormalType",指定 React 全代码页面类型;frontBundleEntry 指向入口文件。

调用数据模型函数

在全代码页面中,可以非常方便地调用数据模型函数,这里建议使用可视化页面将函数参数配置好后,直接复制函数代码到全代码页面中。具体如何获取函数代码,请参考数据模型的增删改查

以获取模型中一条数据为例:

调用模型函数

点击按钮,调用模型的获取一条数据函数,并弹出显示。示例代码如下:

import { Button, message } from 'antd';
import { Jit } from 'jit';

const Render = ({ page }) => {
const handleClick = async () => {
message.success(await page.getData());
};

return (
<div>
<Button type="primary" onClick={handleClick}>
Click Me!
</Button>
</div>
);
};

class PageCls extends Jit.BasePage {
/**
* 获取数据,页面的方法
*/
async getData() {
return JSON.stringify(
await this.app.models.cascadeTableData.get(
Q(Q('id', '=', 1)),
null,
2
)
);
}
}

export { Render, PageCls };

调用模型函数的方法类似: this.app.models.[模型名称].[方法名称]([参数1], [参数2], ...)

调用服务函数

参考调用数据模型函数,只是调用的方法是服务函数,类似: this.app.services.[服务名称].[方法名称]([参数1], [参数2], ...)

Vue全代码页面

对于不熟悉React的开发者,平台也提供了Vue全代码页面。

Vue全代码页面创建

在元素目录树点击搜索框右侧的+按钮,选择页面-vue页面。随后弹出创建vue页面元素的弹窗。

vue创建弹窗

创建弹窗中只需填写名称即可,点击确定完成创建。

vue默认页面

创建完成后会在左侧元素树中显示。默认Vue全代码页面展示了Element Plus UI组件的使用,包含三个功能按钮:打开对话框展示Element Plus组件、调用page实例方法、关闭当前页面,演示了Vue全代码页面的基本交互能力。

基本结构

Vue全代码页面由四个核心文件组成:

<script setup>
import { ref } from 'vue'

const message = ref('Hello JIT!');
const dialogVisible = ref(false);
const props = defineProps({
page: Object
});

const callPageMethod = () => {
alert(props.page.getData());
}
</script>

<template>
<div class="demo">
<h1>{{ message }}</h1>
<h2>当前页面的名称是: {{props.page.title}}</h2>
<el-button plain @click="dialogVisible = true">
element-plus 组件使用
</el-button>
<hr/>
<el-button type="info" @click="callPageMethod">
调用当前 page 实例方法
</el-button>
<hr/>
<el-button type="danger" @click="props.page.closePage">
关闭当前页
</el-button>
</div>

<el-dialog
v-model="dialogVisible"
title="Tips"
width="500"
>
<span>hello World!</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">关闭</el-button>
<el-button type="primary" @click="dialogVisible = false">
确认
</el-button>
</div>
</template>
</el-dialog>
</template>

<style scoped>
.demo{
display: flex;
align-items: center;
flex-direction: column;
}
</style>

App.vue - Vue 组件,使用 Composition API 语法,通过 props 接收 page 实例。

index.ts - 渲染入口,创建 Vue 应用并使用 Element Plus,将 page 实例作为 props 传递给 App 组件。

page.ts - 页面逻辑处理类,继承自 Jit.BasePage,可添加自定义方法供 Vue 组件调用。

e.json - 元素定义文件,type 为 "pages.VueType",指定 Vue 页面类型。

使用 Element Plus 组件

Vue 全代码页面内置了 Element Plus UI 组件库,可以直接使用所有 Element Plus 组件:

<template>
<el-button type="primary">主要按钮</el-button>
<el-dialog v-model="visible">对话框内容</el-dialog>
<el-table :data="tableData">表格组件</el-table>
</template>

与 page 实例交互

Vue 组件通过 props 接收 page 实例,可以调用 page 上的方法和访问属性:

<script setup>
const props = defineProps({
page: Object
});

// 调用page方法
const handleClick = () => {
props.page.getData();
props.page.closePage();
};

// 访问page属性
const pageTitle = props.page.title;
</script>
提示

Vue全代码页面专注于原生Vue开发体验,完整支持数据模型函数服务函数调用以及本地资源引用等核心功能,让你充分发挥Vue生态优势的同时享受平台提供的能力。

相关资料

数据模型的增删改查

后端数据模型提供了完善的增删改查功能,API文档

但是后端的函数只能在后端运行时(服务函数、定时任务函数、事件函数)中才能调用。考虑到这一点,前端环境平台也提供了数据模型的操作接口,如下图:

模型函数

在标准页面的事件面板中,点击函数面板中空白语句上的请选择文案,在面板中选择数据模型-【模型名称】,可看到多个模型操作函数,以查询接口为例,选择获取一条数据

全代码使用模型函数

模型函数的参数较多。考虑到参数的复杂度,开发者可以按以下方式可视化配置参数,并迅速定位到函数代码,直接拷贝到全代码页面中即可。

进入函数

点击参数设置,配置好函数参数,在生成的函数语句最后,点击</>按钮,会跳转到源码区并定位到当前函数语句,复制函数语句await this.app.models.CalendarTestModel.get(Q(Q("id", "=", 1)), null, 2);到全代码中,即可。

注意

注意:页面中的数据模型函数都是以 this.app 开始,如果在使用的地方没有 this.app,请自行添加。

import { getRuntimeApp } from 'jit';
const app = getRuntimeApp();
// app.models.xxx;

服务函数的使用

参考数据模型的增删改查

全代码调用服务函数

参考全代码使用模型函数

使用第三方包

在全代码页面开发中,你可以灵活引入第三方 npm 包来扩展功能。在编辑器的源码模式中修改 package.json 文件,添加所需的依赖包到 dependencies 字段,然后点击“保存”按钮。系统会自动在后端运行 pnpm install 来安装新添加的依赖包,安装完成后即可在代码中正常导入使用。

以rxjs为例,在package.json中添加依赖包:

rxjs

package.jsondependencies 字段添加 rxjs 依赖包,点击“保存”按钮,即可安装依赖。

使用网络资源

系统的打包器集成了从网络导包的能力,但要求网络包是 ES Module 格式,否则会报错。推荐使用 https://esm.sh。如果同样要使用 rxjs,可以在页面中直接引入 import { Observable } from 'https://esm.sh/rxjs'

网络资源

在前端文件中引入 import { Observable } from 'https://esm.sh/rxjs?bundle' 后,即可直接使用第三方包。

提示

esm.sh 还提供了一些优化参数,比如使用 ?bundle 可以将多个 ES Module 压缩成一个文件,从而减少请求次数、提高性能。esm.sh 是一个开源项目,如果用于生产环境,建议自行部署,以提高可用性和安全性。

打包配置的使用

平台的前端打包器基于esbuild封装,配置项与esbuild保持一致。在应用根目录下的jit.config.ts文件中,你可以自定义打包参数来满足特定的构建需求。

打包配置

其中 esBuildOptions 的配置和 esbuild 一致,具体可参考 esbuild 文档

使用源码调试

开发环境可开启 jit.config.tssourcemap 选项;生产环境建议设置为 false,以显著减少产物体积。

引入打包插件

以引入 Less、SCSS 解析插件为例,这两个插件已经集成在平台的打包器 jit-builder 中。可按照使用第三方包的方式在 package.json 中引入 jit-builder

less支持

因为系统默认 package.json 中已经引入了 jit-builder,所以只需将 devDependencies 修改为 dependencies,然后保存。接下来修改打包配置文件 jit.config.ts

样式插件

jit.config.ts 中引入 styleInJsPluginscssInJsPlugin,然后在 plugins 中添加即可。

更多插件

上述方法适用于所有 esbuild 插件。如何找到对应的插件,参考 esbuild 插件

系统内置包一览表

平台预置了常用的第三方库,可以直接在代码中导入使用,无需在 package.json 中声明:

包名版本全局变量名说明
React生态
react18.2.0ReactReact核心库
react-dom18.2.0ReactDomReact DOM 操作库
react-dom/client18.2.0ReactDomClientReact 18 客户端 API
react-dom/server18.2.0ReactDomServerReact 服务端渲染 API
react-router6.18.0ReactRouterReact 路由核心
react-router-dom6.18.0ReactRouterDomReact 路由 DOM 绑定
react-dnd16.0.1ReactDndReact拖拽库
react-dnd-html5-backend16.0.1ReactDndHtml5BackendHTML5拖拽后端
Vue生态
vue3.5.13VueVue.js框架
element-plus2.8.8ElementPlusVue3 UI组件库
UI组件库
antd5.24.0JitAntdAnt Design 组件库
antd-mobile5.33.0antdMobileAnt Design 移动端组件
@ant-design/cssinjs1.17.5antCssInJsAnt Design CSS-in-JS
样式处理
@emotion/react11.13.3EmotionReactCSS‑in‑JS 库
@emotion/styled11.13.0EmotionStyledEmotion 样式组件
@emotion/cache11.13.1EmotionCacheEmotion 缓存
工具库
lodash4.17.21lodashJavaScript工具库
lodash-es4.17.21lodashLodash ES 模块版本
dayjs1.11.11dayjs轻量级日期库
axios1.6.1axiosHTTP 客户端
ahooks3.7.8ahooksReact Hooks 库
localforage1.10.0localforage本地存储库
recast0.23.4recastJavaScript AST 工具
平台专用
jit-JitCoreJitAi 核心库
jit-utils-JitUtilsJitAi 工具库
jit-ui-JitUiJitAi UI 组件库
jit-widgets-JitWidgetsJitAi控件库
直接使用

这些库无需安装即可直接导入使用,例如:import { useState } from 'react'import { Button } from 'antd' 等。

默认loader映射

平台基于 esbuild 构建,以下是系统默认的文件类型处理器配置:

文件类型Loader说明
.pngdataurlPNG图片文件,转为base64内嵌
.jpedataurlJPEG图片文件,转为base64内嵌
.jpegdataurlJPEG图片文件,转为base64内嵌
.gifdataurlGIF动图文件,转为base64内嵌
.svgdataurlSVG矢量图文件,转为base64内嵌
.cssdataurlCSS样式文件,转为base64内嵌
.pytextPython脚本文件,作为文本处理
.webpdataurlWebP图片文件,转为base64内嵌
自定义 loader

如需自定义其他文件类型的处理方式,可在 jit.config.tsesBuildOptions.loader 中进行配置。

相关阅读

全代码组件

了解在页面中使用全代码组件开发,参考:全代码组件