Renderer API 参考
VTJ Renderer API 提供了一套全面的工具,用于将 DSL 模式渲染为 Vue 组件,管理运行时上下文以及处理完整的渲染生命周期。本文档专为需要集成、扩展或自定义渲染系统的高级开发者设计。
架构概述
渲染系统由多个相互连接的模块组成,它们协同工作将 DSL 模式转换为功能性的 Vue 组件:
核心渲染 API
createRenderer(options)
根据 DSL 模式创建 Vue 组件渲染器,处理组件创建的所有方面,包括状态管理、生命周期钩子和节点渲染。
签名:
typescript
function createRenderer(options: CreateRendererOptions): {
renderer: DefineComponent;
context: Context;
};
参数:
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
Vue |
any | globalVue | 用于渲染的 Vue 实例 |
mode |
ContextMode | Runtime | 渲染模式 (Runtime, Design, Raw, VNode) |
dsl |
BlockSchema | required | 要渲染的 DSL 模式 |
components |
Record<string, any> | {} | 组件注册表 |
libs |
Record<string, any> | {} | 库依赖 |
apis |
Record<string, any> | {} | API 函数 |
loader |
BlockLoader | defaultLoader | 组件加载器函数 |
window |
Window | window | 用于样式注入的 Window 对象 |
返回值:
renderer: 准备好进行注册或渲染的 Vue DefineComponentcontext: 管理渲染状态的 Context 实例
示例:
typescript
const { renderer, context } = createRenderer({
Vue,
dsl: myBlockSchema,
components: { ElButton, ElInput },
libs: { lodash: _ },
apis: { fetchUser },
});
app.component("MyBlock", renderer);
来源: packages/renderer/src/render/block.ts#L30-L95
上下文 API
Context 类管理渲染过程中的执行环境,处理表达式解析、函数执行和作用域管理。
构造函数
typescript
class Context {
constructor(options: ContextOptions);
}
选项:
typescript
interface ContextOptions {
mode: ContextMode;
dsl?: BlockSchema;
attrs?: ContextAttrs;
}
关键属性
| 属性 | 类型 | 描述 |
|---|---|---|
__mode |
ContextMode | 当前渲染模式 |
__id |
string | null | 块标识符 |
state |
Record<string, any> | 响应式状态对象 |
context |
Record<string, any> | 执行上下文 |
$refs |
Record<string, any> | 组件引用 |
$components |
Record<string, any> | 组件注册表 |
$libs |
Record<string, any> | 库注册表 |
$apis |
Record<string, any> | API 注册表 |
$provider |
Provider | Provider 实例 |
核心方法
__parseExpression(code)
在上下文中解析和求值 JSExpression 节点。
typescript
__parseExpression(code?: JSExpression | JSFunction): any
示例:
typescript
const value = context.__parseExpression({
type: "JSExpression",
value: "state.count + 1",
});
__parseFunction(code)
从 JSFunction 节点解析并创建函数。
typescript
__parseFunction(code?: JSFunction): Function
示例:
typescript
const handler = context.__parseFunction({
type: "JSFunction",
value: "(event) => console.log(event)",
});
__ref(id, ref)
创建引用处理器以跟踪 DOM 节点和组件实例。
typescript
__ref(id: string | null, ref?: string | Function): (el: any) => void
示例:
typescript
const refHandler = context.__ref("node-123", "myRef");
// 返回函数: (el) => { ... }
__clone(context)
创建一个合并了属性的新上下文,用于作用域渲染(例如 v-for 迭代)。
typescript
__clone(context?: Record<string, any>): Context
示例:
typescript
const iterationContext = context.__clone({ item: data[0], index: 0 });
setup(attrs, Vue)
使用 Vue 实例属性和生命周期钩子初始化上下文。
typescript
setup(attrs: Record<string, any>, Vue?: any): void
节点渲染 API
nodeRender(dsl, context, Vue, loader, brothers, isBranch)
核心渲染函数,将单个节点模式转换为 Vue VNode。
签名:
typescript
function nodeRender(
dsl: NodeSchema,
context: Context,
Vue?: any,
loader?: BlockLoader,
brothers?: NodeSchema[],
isBranch?: boolean,
): VNode | VNode[] | null;
参数:
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
dsl |
NodeSchema | required | 要渲染的节点模式 |
context |
Context | required | 渲染上下文 |
Vue |
any | globalVue | Vue 实例 |
loader |
BlockLoader | defaultLoader | 组件加载器 |
brothers |
NodeSchema[] | [] | 用于 v-if/else-if/else 链的兄弟节点 |
isBranch |
boolean | false | 是否为条件链中的分支 |
支持的功能:
- 条件渲染: v-if, v-else-if, v-else 指令
- 列表渲染: 带有自定义迭代器的 v-for
- 双向绑定: 带修饰符的 v-model
- 可见性控制: v-show 指令
- 指令: 通过应用上下文的自定义指令
- HTML 注入: 用于可信内容的 v-html
- 表达式绑定: 用于动态属性的 v-bind
指令处理
内置指令
渲染器支持在 constants.ts 中定义的这些内置指令:
| 指令 | 描述 | 示例 |
|---|---|---|
vIf |
条件渲染 | { name: 'vIf', value: 'state.visible' } |
vElseIf |
替代条件 | { name: 'vElseIf', value: 'state.alt' } |
vElse |
后备条件 | { name: 'vElse' } |
vFor |
列表迭代 | { name: 'vFor', value: 'items', iterator: { item: 'i', index: 'idx' } } |
vModel |
双向绑定 | { name: 'vModel', value: 'state.value' } |
vShow |
可见性切换 | { name: 'vShow', value: 'state.visible' } |
vBind |
对象绑定 | { name: 'vBind', value: 'state.props' } |
vHtml |
HTML 内容 | { name: 'vHtml', value: 'state.content' } |
getModifiers(modifiers, isToString?)
从指令修饰符中提取并格式化修饰符名称。
typescript
function getModifiers(
modifiers: NodeModifiers = {},
isToString?: boolean,
): string[];
示例:
typescript
const mods = getModifiers({ prevent: true, stop: true });
// 返回: ['prevent', 'stop']
块加载器 API
defaultLoader(name, from, Vue)
默认组件加载器,仅返回组件名称。
typescript
const defaultLoader: BlockLoader = (name: string) => name;
createLoader(opts)
创建增强型块加载器,支持异步组件、模式块、基于 URL 的模式和插件。
签名:
typescript
function createLoader(opts: CreateLoaderOptions): BlockLoader;
选项:
typescript
interface CreateLoaderOptions {
getDsl: (id: string) => Promise<BlockSchema | null>;
getDslByUrl: (url: string) => Promise<BlockSchema | null>;
options: Partial<CreateRendererOptions>;
}
加载器类型:
| 来源类型 | 描述 | 示例 |
|---|---|---|
string |
直接组件名称 | 'ElButton' |
Schema |
通过 ID 的块模式 | { type: 'Schema', id: 'block-123' } |
UrlSchema |
来自 URL 的模式 | { type: 'UrlSchema', url: 'https://...' } |
Plugin |
插件组件 | { type: 'Plugin', library: 'MyLib', urls: [...] } |
getPlugin(from, global)
从 URL 异步加载插件组件。
typescript
async function getPlugin(
from: NodeFromPlugin,
global?: any,
): Promise<BlockPlugin | null>;
示例:
typescript
const plugin = await getPlugin({
library: "MyPlugin",
urls: [
"https://cdn.example.com/plugin.css",
"https://cdn.example.com/plugin.js",
],
});
clearLoaderCache()
清除所有缓存的加载器和队列操作。
typescript
function clearLoaderCache(): void;
Provider API
Provider 类是项目管理、服务协调和资源加载的核心协调器。
构造函数
typescript
class Provider extends Base {
constructor(public options: ProviderOptions)
}
选项:
typescript
interface ProviderOptions {
service: Service;
project?: Partial<ProjectSchema>;
modules?: Record<string, () => Promise<any>>;
mode?: ContextMode;
adapter?: Partial<ProvideAdapter>;
router?: Router;
dependencies?: Record<string, () => Promise<any>>;
materials?: Record<string, () => Promise<any>>;
libraryOptions?: Record<string, any>;
globals?: Record<string, any>;
materialPath?: string;
nodeEnv?: NodeEnv;
install?: (app: App) => void;
routeAppendTo?: RouteRecordName;
pageRouteName?: string;
routeMeta?: RouteMeta;
enhance?: (app: App, provider: Provider) => void;
vtjDir?: string;
vtjRawDir?: string;
enableStaticRoute?: boolean;
}
关键属性
| 属性 | 类型 | 描述 |
|---|---|---|
mode |
ContextMode | 当前执行模式 |
globals |
Record<string, any> | 全局变量 |
modules |
Record<string, Function> | 异步模块加载器 |
adapter |
ProvideAdapter | 服务适配器 |
apis |
Record<string, Function> | API 函数 |
dependencies |
Record<string, Function> | 依赖加载器 |
materials |
Record<string, Function> | 物料加载器 |
library |
Record<string, any> | 已加载的库 |
service |
Service | 核心服务实例 |
project |
ProjectSchema | 当前项目配置 |
components |
Record<string, any> | 组件注册表 |
核心方法
load(project)
加载并初始化项目,包括依赖、模拟数据、API 和路由。
typescript
async load(project: ProjectSchema): Promise<void>
初始化步骤:
- 从模块或服务加载项目模式
- 加载依赖(Raw 模式)或完整资源(其他模式)
- 初始化 Mock.js 配置
- 从模式创建 API 接口
- 初始化路由(非 uniapp 平台)
- 触发就绪事件
createMock(func)
使用 Mock.js 创建模拟数据生成器。
typescript
createMock(func: (...args) => any): (...args) => Promise<any>
示例:
typescript
const mockUser = provider.createMock(() => ({
name: "@name",
email: "@email",
}));
const user = await mockUser();
loadDependencies(_window)
加载依赖模块并在全局注册它们。
typescript
private async loadDependencies(_window: any = {}): Promise<void>
loadAssets(_window)
加载所有项目资源,包括库、样式和物料。
typescript
private async loadAssets(_window: any = {}): Promise<void>
资源加载过程:
- 解析依赖配置
- 加载库脚本和 CSS
- 注册内置组件
- 加载物料描述
- 注册物料组件
initRouter()
使用页面和主页路由初始化 Vue Router。
typescript
private initRouter(): void
服务 API
BaseService 类
提供所有后端集成方法的基础服务实现。
构造函数:
typescript
class BaseService implements Service {
constructor(public req: IStaticRequest = request)
}
服务方法
| 方法 | 描述 | 返回值 |
|---|---|---|
getExtension() |
获取扩展配置 | Promise<VTJConfig> |
init(project) |
初始化项目模式 | Promise<ProjectSchema> |
saveProject(project, type?) |
保存项目 | Promise<boolean> |
saveMaterials(project, materials) |
保存物料描述 | Promise<boolean> |
saveFile(file) |
保存块模式 | Promise<boolean> |
getFile(id) |
获取块模式 | Promise<BlockSchema> |
removeFile(id) |
删除文件 | Promise<boolean> |
saveHistory(history) |
保存历史记录 | Promise<boolean> |
getHistory(id) |
获取历史记录 | Promise<HistorySchema> |
getHistoryItem(fId, id) |
获取历史记录项 | Promise<HistoryItem> |
saveHistoryItem(fId, item) |
保存历史记录项 | Promise<boolean> |
removeHistoryItem(fId, ids) |
删除历史记录项 | Promise<boolean> |
publish(project) |
发布项目 | Promise<boolean> |
publishFile(project, file) |
发布文件 | Promise<boolean> |
genVueContent(project, dsl) |
生成 Vue 代码 | Promise<string> |
parseVue(project, options) |
解析 Vue 为 DSL | Promise<BlockSchema> |
createRawPage(file) |
创建原始页面 | Promise<boolean> |
removeRawPage(id) |
删除原始页面 | Promise<boolean> |
uploadStaticFile(file, projectId) |
上传静态文件 | Promise<StaticFileInfo> |
getStaticFiles(projectId) |
获取静态文件 | Promise<StaticFileInfo[]> |
removeStaticFile(name, projectId) |
删除静态文件 | Promise<boolean> |
clearStaticFiles(projectId) |
清除静态文件 | Promise<boolean> |
getPluginMaterial(from) |
获取插件物料 | Promise<MaterialDescription> |
genSource(project) |
生成源代码 | Promise<string> |
辅助函数
createServiceRequest(notify?)
创建已配置的 HTTP 请求服务。
typescript
function createServiceRequest(notify?: (msg: string) => void): IStaticRequest;
常量和枚举
ContextMode 枚举
定义不同的渲染模式:
typescript
enum ContextMode {
Runtime = "Runtime", // 生产运行时
Design = "Design", // 设计器模式
Raw = "Raw", // 源代码模式
VNode = "VNode", // 虚拟节点模式
}
NodeEnv 枚举
环境类型定义:
typescript
enum NodeEnv {
Production = "production",
Development = "development",
}
内置常量
| 常量 | 描述 | 值 |
|---|---|---|
CONTEXT_HOST |
Vue 实例属性名称 | ['$el', '$emit', '$nextTick', ...] |
LIFE_CYCLES_LIST |
生命周期钩子 | ['beforeCreate', 'created', ...] |
BUILT_IN_DIRECTIVES |
支持的指令 | ['vIf', 'vElseIf', 'vElse', ...] |
DATA_TYPES |
Prop 数据类型 | { String, Number, Boolean, ... } |
PAGE_ROUTE_NAME |
页面路由名称 | 'VtjPage' |
HOMEPAGE_ROUTE_NAME |
主页路由名称 | 'VtjHomepage' |
HTML_TAGS |
原生 HTML 标签 | 逗号分隔的标签列表 |
BUILD_IN_TAGS |
内置组件标签 | ['component', 'slot'] |
工具函数
createDataSources(dataSources, context)
创建用于 API 调用和模拟数据的数据源函数。
typescript
function createDataSources(
dataSources: Record<string, DataSourceSchema>,
context: Context,
): Record<string, DataSourceHandler>;
数据源类型:
mock: 使用 Mock.js 生成数据api: 调用注册的 API 函数,并可选进行转换
createProps(props, context)
创建具有类型验证和默认值的组件 props 定义。
typescript
function createProps(
props: Array<string | BlockProp>,
context: Context,
): Record<string, PropOptions>;
createState(Vue, state, context)
创建响应式状态对象。
typescript
function createState(
Vue: any,
state: BlockState,
context: Context,
): Record<string, any>;
createComputed(Vue, computedSchema, context)
创建计算属性。
typescript
function createComputed(
Vue: any,
computedSchema: Record<string, JSFunction>,
context: Context,
): Record<string, ComputedRef>;
createMethods(methods, context)
创建方法函数。
typescript
function createMethods(
methods: Record<string, JSFunction>,
context: Context,
): Record<string, Function>;
setWatches(Vue, watches, context)
为响应式数据设置监视器。
typescript
function setWatches(Vue: any, watches: BlockWatch[], context: Context): void;
createLifeCycles(lifeCycle, context)
创建生命周期钩子处理器。
typescript
function createLifeCycles(
lifeCycle: Record<string, JSFunction>,
context: Context,
): Record<string, Function>;
插件系统
Access 插件
Access 插件提供身份验证和授权功能。
获取位置: packages/renderer/src/plugins/access.ts
💡 Access 插件与 ACCESS 常量中定义的全局身份验证端点和存储密钥集成。当 provider 配置了访问适配器时,它会自动初始化。
集成示例
基础组件渲染
typescript
import { createRenderer } from "@vtj/renderer";
import * as Vue from "vue";
const { renderer } = createRenderer({
Vue,
dsl: {
id: "my-block",
name: "MyBlock",
state: { count: 0 },
nodes: [
{
id: "button-1",
name: "el-button",
props: { type: "primary" },
events: {
click: { type: "JSFunction", value: "state.count++" },
},
children: `Count: ${"state.count"}`,
},
],
},
components: { ElButton },
});
// 在 Vue 应用中注册
app.component("MyComponent", renderer);
动态块加载
typescript
import { createLoader, createRenderer } from "@vtj/renderer";
const loader = createLoader({
async getDsl(id) {
const response = await fetch(`/api/blocks/${id}`);
return response.json();
},
async getDslByUrl(url) {
const response = await fetch(url);
return response.json();
},
options: {
Vue,
components: { ElButton },
loader: null, // 将递归设置
},
});
// 在渲染器中使用加载器
const { renderer } = createRenderer({
Vue,
dsl: parentSchema,
loader,
});
Provider 集成
typescript
import { Provider } from "@vtj/renderer";
import { BaseService, createServiceRequest } from "@vtj/renderer";
const provider = new Provider({
service: new BaseService(createServiceRequest()),
mode: ContextMode.Runtime,
project: { id: "my-project" },
router,
dependencies: {
ElementPlus: () => import("element-plus"),
},
materials: {
MyMaterials: () => import("./materials"),
},
});
// 加载项目
await provider.load({ id: "my-project" });
// 访问组件和 API
const components = provider.components;
const apis = provider.apis;
API 参考摘要
| 模块 | 用途 | 主要导出 |
|---|---|---|
render/block |
组件渲染 | createRenderer, createDataSources |
render/context |
上下文管理 | Context 类 |
render/node |
节点渲染 | nodeRender, getModifiers |
render/loader |
块加载 | createLoader, getPlugin, clearLoaderCache |
provider |
项目管理 | Provider 类, providerKey |
services/base |
服务层 | BaseService, createServiceRequest |
constants |
常量 | ContextMode, BUILT_IN_DIRECTIVES, DATA_TYPES |
utils |
工具函数 | isJSExpression, isJSFunction, parseDeps |
plugins |
插件 | 访问控制插件 |
hooks |
钩子 | 与遮罩相关的钩子 |
💡 所有 API 均支持 TypeScript 并提供全面的类型定义。从
@vtj/core导入 DSL 模式的类型,从@vtj/renderer导入运行时接口的渲染器特定类型。
相关文档
- Engine API Reference: 了解与渲染器协同工作的引擎核心 API
- Provider API Reference: 深入了解 provider 系统和服务集成
- Renderer System and Runtime: 理解渲染器架构和生命周期
- DSL Schema and Data Models: 用于渲染的 DSL 模式结构
参考资料
- 官方文档:vtj.pro/
- 在线平台:app.vtj.pro/
- 开源仓库:gitee.com/newgateway/...