Files
vtj/renderer.md
“chenhuachun” d2e212aa68 docs: ✏️ docs
2025-06-28 16:50:04 +08:00

221 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# createRenderer 函数详解
`createRenderer` 是 VTJ 渲染系统的核心函数,用于根据 DSL (Domain Specific Language) 创建 Vue 组件渲染器。
## 作用
1. **组件渲染器创建**:基于 DSL 配置生成可复用的 Vue 组件
2. **上下文管理**:创建并维护组件运行时上下文(Context)
3. **响应式系统集成**:处理状态(state)、计算属性(computed)和方法(methods)
4. **生命周期管理**:集成 DSL 定义的生命周期钩子
5. **跨框架支持**:通过抽象层支持不同版本的 Vue
## 工作原理
### 输入参数 (`CreateRendererOptions`)
```typescript
interface CreateRendererOptions {
Vue?: any; // Vue 实例 (默认为全局 Vue)
mode?: ContextMode; // 上下文模式 (默认 Runtime)
dsl?: BlockSchema; // 块定义 DSL
components?: Record<string, any>; // 可用组件
libs?: Record<string, any>; // 第三方库
apis?: Record<string, any>; // API 集合
loader?: BlockLoader; // 块加载器
window?: Window; // 目标窗口对象
}
```
### 核心工作流程
1. **初始化上下文**
```typescript
const context = new Context({
mode,
dsl: dsl.value,
attrs: { $components, $libs, $apis }
});
```
2. **创建 Vue 组件**
- 使用 `Vue.defineComponent` 定义组件
- 处理 props、setup、render 等核心选项
3. **响应式系统集成**
```typescript
context.state = createState(Vue, dsl.value.state, context);
const computed = createComputed(Vue, dsl.value.computed, context);
const methods = createMethods(dsl.value.methods, context);
```
4. **依赖注入处理**
```typescript
const injects = createInject(Vue, dsl.value.inject, context);
```
5. **数据源初始化**
```typescript
const dataSources = createDataSources(dsl.value.dataSources, context);
```
6. **生命周期管理**
```typescript
...createLifeCycles(dsl.value.lifeCycles, context)
```
7. **渲染逻辑**
```typescript
render() {
const nodes: NodeSchema[] = dsl.value.nodes || [];
// 单节点渲染
if (nodes.length === 1) return nodeRender(nodes[0], context, Vue, loader, nodes);
// 多节点渲染
return nodes.map(child => nodeRender(child, context, Vue, loader, nodes));
}
```
### 关键辅助函数
1. **`createProps()`** - 处理组件 props
- 支持字符串和对象形式定义
- 自动解析 JS 表达式默认值
```typescript
const propsDef = createProps(dsl.value.props, context);
```
2. **`createState()`** - 创建响应式状态
- 使用 `Vue.reactive` 创建响应式对象
- 自动解析 JS 表达式和函数
3. **`createComputed()`** - 创建计算属性
- 使用 `Vue.computed` 包装计算逻辑
4. **`createDataSources()`** - 初始化数据源
- 支持 mock 和 API 两种类型
- 自动处理数据转换
5. **`setWatches()`** - 设置侦听器
```typescript
Vue.watch(
context.__parseExpression(n.source),
context.__parseFunction(n.handler),
{ deep, immediate }
);
```
## 使用方法
### 基本使用
```typescript
import { createRenderer } from '@vtj/renderer';
const { renderer, context } = createRenderer({
Vue, // 可选 Vue 实例
dsl: blockSchema, // 块定义 DSL
components: { Button, Input }, // 注册组件
apis: { fetchData } // 注册 API
});
// 在 Vue 应用中作为组件使用
app.component('BlockRenderer', renderer);
```
### DSL 配置示例
```json
{
"id": "my-block",
"name": "MyBlock",
"props": [{ "name": "title", "type": "string", "required": true }],
"state": {
"count": 0,
"message": "Hello VTJ"
},
"methods": {
"increment": {
"type": "JSFunction",
"value": "function() { this.count++ }"
}
},
"nodes": [
{
"type": "element",
"tag": "div",
"children": [
{ "type": "text", "value": "{{ title }}" },
{
"type": "element",
"tag": "button",
"events": { "click": "increment" }
}
]
}
]
}
```
### 高级功能
1. **依赖注入**
```json
"inject": [
{ "name": "theme", "from": "THEME_PROVIDER", "default": "light" }
]
```
2. **数据源配置**
```json
"dataSources": {
"userData": {
"type": "api",
"ref": "getUserInfo",
"transform": {
"type": "JSFunction",
"value": "function(data) { return data.user }"
}
}
}
```
3. **生命周期钩子**
```json
"lifeCycles": {
"mounted": {
"type": "JSFunction",
"value": "function() { console.log('组件挂载') }"
}
}
```
## 最佳实践
1. **组件拆分**:复杂 UI 拆分为多个 block
2. **状态管理**:优先使用块级 state复杂场景考虑外部状态管理
3. **性能优化**
- 使用 `Vue.markRaw` 避免不必要的响应式转换
- 合理使用计算属性缓存复杂运算
4. **样式隔离**:利用 `adoptedStyleSheets` 实现 CSS 隔离
5. **错误处理**:在数据源中添加错误处理逻辑
## 注意事项
1. 确保 DSL 中的 JS 表达式/函数可安全执行
2. 跨窗口渲染时提供正确的 window 对象
3. 生产环境移除调试用的 mock 数据源
4. 避免在 render 函数中进行复杂计算