数据引擎与状态管理是低代码平台的核心基础设施,负责处理应用的数据流、状态同步、数据绑定等关键功能。本章将详细介绍如何设计和实现一个高效、可扩展的数据引擎系统。
6.1 数据引擎架构设计
6.1.1 整体架构概览
## 6.4 数据绑定引擎
### 6.4.1 数据绑定核心
```typescript
// 数据绑定类型
enum BindingType {
ONE_WAY = 'one_way',
TWO_WAY = 'two_way',
ONE_TIME = 'one_time'
}
// 绑定表达式
interface BindingExpression {
expression: string;
dependencies: string[];
compiled?: Function;
}
// 数据绑定
interface DataBinding {
id: string;
sourceId: string;
targetId: string;
sourcePath: string;
targetPath: string;
type: BindingType;
expression?: BindingExpression;
transform?: TransformFunction;
validator?: ValidatorFunction;
active: boolean;
}
// 变换函数
type TransformFunction = (value: any, context: BindingContext) => any;
// 验证函数
type ValidatorFunction = (value: any, context: BindingContext) => boolean;
// 绑定上下文
interface BindingContext {
sourceValue: any;
targetValue: any;
binding: DataBinding;
timestamp: number;
}
// 数据绑定引擎
class DataBindingEngine {
private bindings: Map<string, DataBinding> = new Map();
private watchers: Map<string, Set<string>> = new Map(); // path -> binding ids
private stateManager: StateManager;
private eventBus: EventBus;
private expressionCompiler: ExpressionCompiler;
constructor(eventBus: EventBus, stateManager: StateManager) {
this.eventBus = eventBus;
this.stateManager = stateManager;
this.expressionCompiler = new ExpressionCompiler();
}
async initialize(): Promise<void> {
// 监听状态变化
this.eventBus.on('state:changed', this.handleStateChange.bind(this));
console.log('数据绑定引擎初始化完成');
}
// 创建数据绑定
createBinding(binding: Omit<DataBinding, 'id' | 'active'>): string {
const id = this.generateBindingId();
const fullBinding: DataBinding = {
...binding,
id,
active: true
};
// 编译表达式
if (fullBinding.expression) {
fullBinding.expression.compiled = this.expressionCompiler.compile(fullBinding.expression.expression);
}
// 注册绑定
this.bindings.set(id, fullBinding);
// 注册监听器
this.registerWatcher(fullBinding.sourcePath, id);
// 如果是双向绑定,也监听目标路径
if (fullBinding.type === BindingType.TWO_WAY) {
this.registerWatcher(fullBinding.targetPath, id);
}
// 初始同步
this.syncBinding(fullBinding);
this.eventBus.emit('binding:created', { id, binding: fullBinding });
return id;
}
// 移除数据绑定
removeBinding(id: string): void {
const binding = this.bindings.get(id);
if (!binding) {
return;
}
// 移除监听器
this.unregisterWatcher(binding.sourcePath, id);
if (binding.type === BindingType.TWO_WAY) {
this.unregisterWatcher(binding.targetPath, id);
}
// 移除绑定
this.bindings.delete(id);
this.eventBus.emit('binding:removed', { id });
}
// 激活/停用绑定
setBindingActive(id: string, active: boolean): void {
const binding = this.bindings.get(id);
if (binding) {
binding.active = active;
this.eventBus.emit('binding:toggled', { id, active });
}
}
// 获取绑定
getBinding(id: string): DataBinding | undefined {
return this.bindings.get(id);
}
// 获取所有绑定
getAllBindings(): DataBinding[] {
return Array.from(this.bindings.values());
}
// 根据路径获取相关绑定
getBindingsByPath(path: string): DataBinding[] {
const bindingIds = this.watchers.get(path) || new Set();
return Array.from(bindingIds).map(id => this.bindings.get(id)!).filter(Boolean);
}
// 手动同步绑定
syncBinding(binding: DataBinding): void {
if (!binding.active) {
return;
}
try {
const sourceValue = this.stateManager.getState(binding.sourcePath);
let targetValue = sourceValue;
// 应用表达式
if (binding.expression && binding.expression.compiled) {
const context = this.createBindingContext(binding, sourceValue);
targetValue = binding.expression.compiled(context);
}
// 应用变换
if (binding.transform) {
const context = this.createBindingContext(binding, sourceValue, targetValue);
targetValue = binding.transform(targetValue, context);
}
// 验证值
if (binding.validator) {
const context = this.createBindingContext(binding, sourceValue, targetValue);
if (!binding.validator(targetValue, context)) {
console.warn(`数据绑定验证失败: ${binding.id}`);
return;
}
}
// 设置目标值
this.stateManager.setState(binding.targetPath, targetValue);
this.eventBus.emit('binding:synced', {
bindingId: binding.id,
sourceValue,
targetValue,
timestamp: Date.now()
});
} catch (error) {
console.error(`数据绑定同步失败: ${binding.id}`, error);
this.eventBus.emit('binding:error', {
bindingId: binding.id,
error,
timestamp: Date.now()
});
}
}
// 批量同步绑定
syncBindings(bindingIds: string[]): void {
bindingIds.forEach(id => {
const binding = this.bindings.get(id);
if (binding) {
this.syncBinding(binding);
}
});
}
// 处理状态变化
private handleStateChange(event: { path: string; newValue: any; oldValue: any }): void {
const affectedBindings = this.getBindingsByPath(event.path);
affectedBindings.forEach(binding => {
// 避免循环绑定
if (this.isCircularBinding(binding, event.path)) {
return;
}
this.syncBinding(binding);
});
}
// 检查循环绑定
private isCircularBinding(binding: DataBinding, changedPath: string): boolean {
// 简化的循环检测逻辑
return binding.type === BindingType.TWO_WAY &&
binding.targetPath === changedPath &&
binding.sourcePath !== changedPath;
}
// 创建绑定上下文
private createBindingContext(binding: DataBinding, sourceValue?: any, targetValue?: any): BindingContext {
return {
sourceValue: sourceValue !== undefined ? sourceValue : this.stateManager.getState(binding.sourcePath),
targetValue: targetValue !== undefined ? targetValue : this.stateManager.getState(binding.targetPath),
binding,
timestamp: Date.now()
};
}
// 注册监听器
private registerWatcher(path: string, bindingId: string): void {
if (!this.watchers.has(path)) {
this.watchers.set(path, new Set());
}
this.watchers.get(path)!.add(bindingId);
}
// 取消注册监听器
private unregisterWatcher(path: string, bindingId: string): void {
const watchers = this.watchers.get(path);
if (watchers) {
watchers.delete(bindingId);
if (watchers.size === 0) {
this.watchers.delete(path);
}
}
}
// 生成绑定ID
private generateBindingId(): string {
return `binding_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
async destroy(): Promise<void> {
this.bindings.clear();
this.watchers.clear();
console.log('数据绑定引擎已销毁');
}
}
// 表达式编译器
class ExpressionCompiler {
private cache: Map<string, Function> = new Map();
compile(expression: string): Function {
if (this.cache.has(expression)) {
return this.cache.get(expression)!;
}
try {
// 简化的表达式编译
// 实际实现应该使用更安全的表达式解析器
const func = new Function('context', `
with(context) {
return ${expression};
}
`);
this.cache.set(expression, func);
return func;
} catch (error) {
console.error(`表达式编译失败: ${expression}`, error);
return () => undefined;
}
}
clearCache(): void {
this.cache.clear();
}
}
6.4.2 数据绑定工具
// 数据绑定构建器
class DataBindingBuilder {
private binding: Partial<DataBinding> = {};
private bindingEngine: DataBindingEngine;
constructor(bindingEngine: DataBindingEngine) {
this.bindingEngine = bindingEngine;
}
// 设置源
from(sourceId: string, sourcePath: string): this {
this.binding.sourceId = sourceId;
this.binding.sourcePath = sourcePath;
return this;
}
// 设置目标
to(targetId: string, targetPath: string): this {
this.binding.targetId = targetId;
this.binding.targetPath = targetPath;
return this;
}
// 设置绑定类型
type(type: BindingType): this {
this.binding.type = type;
return this;
}
// 设置表达式
expression(expr: string): this {
this.binding.expression = {
expression: expr,
dependencies: this.extractDependencies(expr)
};
return this;
}
// 设置变换函数
transform(transform: TransformFunction): this {
this.binding.transform = transform;
return this;
}
// 设置验证函数
validate(validator: ValidatorFunction): this {
this.binding.validator = validator;
return this;
}
// 创建绑定
build(): string {
if (!this.binding.sourceId || !this.binding.targetId ||
!this.binding.sourcePath || !this.binding.targetPath ||
!this.binding.type) {
throw new Error('绑定配置不完整');
}
return this.bindingEngine.createBinding(this.binding as Omit<DataBinding, 'id' | 'active'>);
}
// 提取依赖项
private extractDependencies(expression: string): string[] {
// 简化的依赖提取逻辑
// 实际实现应该使用AST解析
const matches = expression.match(/\b[a-zA-Z_$][a-zA-Z0-9_$.]*\b/g) || [];
return [...new Set(matches)];
}
}
// 数据绑定管理器
class DataBindingManager {
private bindingEngine: DataBindingEngine;
private bindingGroups: Map<string, Set<string>> = new Map();
constructor(bindingEngine: DataBindingEngine) {
this.bindingEngine = bindingEngine;
}
// 创建绑定构建器
createBuilder(): DataBindingBuilder {
return new DataBindingBuilder(this.bindingEngine);
}
// 创建绑定组
createGroup(groupId: string): void {
if (!this.bindingGroups.has(groupId)) {
this.bindingGroups.set(groupId, new Set());
}
}
// 添加绑定到组
addToGroup(groupId: string, bindingId: string): void {
if (!this.bindingGroups.has(groupId)) {
this.createGroup(groupId);
}
this.bindingGroups.get(groupId)!.add(bindingId);
}
// 从组中移除绑定
removeFromGroup(groupId: string, bindingId: string): void {
const group = this.bindingGroups.get(groupId);
if (group) {
group.delete(bindingId);
if (group.size === 0) {
this.bindingGroups.delete(groupId);
}
}
}
// 激活/停用绑定组
setGroupActive(groupId: string, active: boolean): void {
const group = this.bindingGroups.get(groupId);
if (group) {
group.forEach(bindingId => {
this.bindingEngine.setBindingActive(bindingId, active);
});
}
}
// 同步绑定组
syncGroup(groupId: string): void {
const group = this.bindingGroups.get(groupId);
if (group) {
this.bindingEngine.syncBindings(Array.from(group));
}
}
// 移除绑定组
removeGroup(groupId: string): void {
const group = this.bindingGroups.get(groupId);
if (group) {
group.forEach(bindingId => {
this.bindingEngine.removeBinding(bindingId);
});
this.bindingGroups.delete(groupId);
}
}
// 获取组中的绑定
getGroupBindings(groupId: string): DataBinding[] {
const group = this.bindingGroups.get(groupId);
if (!group) {
return [];
}
return Array.from(group)
.map(id => this.bindingEngine.getBinding(id))
.filter(Boolean) as DataBinding[];
}
}
6.5 数据变换引擎
6.5.1 数据变换核心
// 变换类型
enum TransformType {
MAP = 'map',
FILTER = 'filter',
REDUCE = 'reduce',
SORT = 'sort',
GROUP = 'group',
AGGREGATE = 'aggregate',
JOIN = 'join',
CUSTOM = 'custom'
}
// 变换配置
interface TransformConfig {
id: string;
name: string;
type: TransformType;
input: TransformInput;
output: TransformOutput;
parameters: Record<string, any>;
function?: TransformFunction;
}
// 变换输入
interface TransformInput {
source: string;
path?: string;
schema?: any;
}
// 变换输出
interface TransformOutput {
target: string;
path?: string;
schema?: any;
}
// 变换结果
interface TransformResult {
success: boolean;
data?: any;
error?: string;
metadata: {
inputCount: number;
outputCount: number;
duration: number;
timestamp: number;
};
}
// 数据变换引擎
class DataTransformEngine {
private transforms: Map<string, TransformConfig> = new Map();
private transformFunctions: Map<TransformType, TransformFunction> = new Map();
constructor(config: TransformConfig[]) {
this.initializeBuiltinTransforms();
// 注册配置中的变换
config.forEach(transform => {
this.registerTransform(transform);
});
}
// 注册变换
registerTransform(config: TransformConfig): void {
this.transforms.set(config.id, config);
if (config.function) {
this.transformFunctions.set(config.type, config.function);
}
}
// 执行变换
async transform(transformId: string, data: any): Promise<TransformResult> {
const config = this.transforms.get(transformId);
if (!config) {
return {
success: false,
error: `变换未找到: ${transformId}`,
metadata: {
inputCount: 0,
outputCount: 0,
duration: 0,
timestamp: Date.now()
}
};
}
const startTime = Date.now();
try {
const transformFunction = this.getTransformFunction(config.type);
if (!transformFunction) {
throw new Error(`变换函数未找到: ${config.type}`);
}
const inputCount = Array.isArray(data) ? data.length : 1;
const result = await transformFunction(data, config.parameters);
const outputCount = Array.isArray(result) ? result.length : 1;
return {
success: true,
data: result,
metadata: {
inputCount,
outputCount,
duration: Date.now() - startTime,
timestamp: Date.now()
}
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error),
metadata: {
inputCount: Array.isArray(data) ? data.length : 1,
outputCount: 0,
duration: Date.now() - startTime,
timestamp: Date.now()
}
};
}
}
// 批量变换
async batchTransform(transformIds: string[], data: any): Promise<TransformResult[]> {
const results: TransformResult[] = [];
let currentData = data;
for (const transformId of transformIds) {
const result = await this.transform(transformId, currentData);
results.push(result);
if (result.success) {
currentData = result.data;
} else {
break; // 如果某个变换失败,停止后续变换
}
}
return results;
}
// 获取变换函数
private getTransformFunction(type: TransformType): TransformFunction | undefined {
return this.transformFunctions.get(type);
}
// 初始化内置变换
private initializeBuiltinTransforms(): void {
// Map 变换
this.transformFunctions.set(TransformType.MAP, (data: any[], params: any) => {
if (!Array.isArray(data)) {
throw new Error('Map 变换需要数组输入');
}
const { mapper } = params;
if (typeof mapper !== 'function') {
throw new Error('Map 变换需要 mapper 函数');
}
return data.map(mapper);
});
// Filter 变换
this.transformFunctions.set(TransformType.FILTER, (data: any[], params: any) => {
if (!Array.isArray(data)) {
throw new Error('Filter 变换需要数组输入');
}
const { predicate } = params;
if (typeof predicate !== 'function') {
throw new Error('Filter 变换需要 predicate 函数');
}
return data.filter(predicate);
});
// Sort 变换
this.transformFunctions.set(TransformType.SORT, (data: any[], params: any) => {
if (!Array.isArray(data)) {
throw new Error('Sort 变换需要数组输入');
}
const { compareFn, field, order = 'asc' } = params;
if (compareFn && typeof compareFn === 'function') {
return [...data].sort(compareFn);
}
if (field) {
return [...data].sort((a, b) => {
const aVal = a[field];
const bVal = b[field];
if (aVal < bVal) return order === 'asc' ? -1 : 1;
if (aVal > bVal) return order === 'asc' ? 1 : -1;
return 0;
});
}
return [...data].sort();
});
// Group 变换
this.transformFunctions.set(TransformType.GROUP, (data: any[], params: any) => {
if (!Array.isArray(data)) {
throw new Error('Group 变换需要数组输入');
}
const { keyFn, field } = params;
const getKey = keyFn || ((item: any) => item[field]);
const groups = new Map();
data.forEach(item => {
const key = getKey(item);
if (!groups.has(key)) {
groups.set(key, []);
}
groups.get(key).push(item);
});
return Object.fromEntries(groups);
});
// Aggregate 变换
this.transformFunctions.set(TransformType.AGGREGATE, (data: any[], params: any) => {
if (!Array.isArray(data)) {
throw new Error('Aggregate 变换需要数组输入');
}
const { operations } = params;
const result: any = {};
operations.forEach((op: any) => {
const { field, operation, alias } = op;
const values = data.map(item => item[field]).filter(val => val != null);
switch (operation) {
case 'sum':
result[alias || `${field}_sum`] = values.reduce((sum, val) => sum + val, 0);
break;
case 'avg':
result[alias || `${field}_avg`] = values.reduce((sum, val) => sum + val, 0) / values.length;
break;
case 'min':
result[alias || `${field}_min`] = Math.min(...values);
break;
case 'max':
result[alias || `${field}_max`] = Math.max(...values);
break;
case 'count':
result[alias || `${field}_count`] = values.length;
break;
}
});
return result;
});
}
}
6.5.2 数据验证引擎
// 验证规则类型
enum ValidationRuleType {
REQUIRED = 'required',
TYPE = 'type',
MIN_LENGTH = 'min_length',
MAX_LENGTH = 'max_length',
MIN_VALUE = 'min_value',
MAX_VALUE = 'max_value',
PATTERN = 'pattern',
CUSTOM = 'custom'
}
// 验证规则
interface ValidationRule {
type: ValidationRuleType;
value?: any;
message?: string;
validator?: (value: any) => boolean;
}
// 验证结果
interface ValidationResult {
valid: boolean;
errors: ValidationError[];
}
// 验证错误
interface ValidationError {
field: string;
rule: ValidationRuleType;
message: string;
value: any;
}
// 数据验证引擎
class DataValidationEngine {
private schemas: Map<string, ValidationSchema> = new Map();
private validators: Map<ValidationRuleType, ValidatorFunction> = new Map();
constructor(config: ValidationConfig) {
this.initializeBuiltinValidators();
// 注册配置中的模式
if (config.schemas) {
config.schemas.forEach(schema => {
this.registerSchema(schema);
});
}
}
// 注册验证模式
registerSchema(schema: ValidationSchema): void {
this.schemas.set(schema.id, schema);
}
// 验证数据
validate(schemaId: string, data: any): ValidationResult {
const schema = this.schemas.get(schemaId);
if (!schema) {
return {
valid: false,
errors: [{
field: '',
rule: ValidationRuleType.CUSTOM,
message: `验证模式未找到: ${schemaId}`,
value: data
}]
};
}
const errors: ValidationError[] = [];
// 验证每个字段
Object.entries(schema.fields).forEach(([field, rules]) => {
const fieldValue = this.getFieldValue(data, field);
const fieldErrors = this.validateField(field, fieldValue, rules);
errors.push(...fieldErrors);
});
return {
valid: errors.length === 0,
errors
};
}
// 验证字段
private validateField(field: string, value: any, rules: ValidationRule[]): ValidationError[] {
const errors: ValidationError[] = [];
for (const rule of rules) {
const validator = this.getValidator(rule.type);
if (!validator) {
continue;
}
if (!validator(value, rule.value)) {
errors.push({
field,
rule: rule.type,
message: rule.message || this.getDefaultMessage(rule.type, field, rule.value),
value
});
}
}
return errors;
}
// 获取验证器
private getValidator(type: ValidationRuleType): ValidatorFunction | undefined {
return this.validators.get(type);
}
// 获取字段值
private getFieldValue(data: any, field: string): any {
const keys = field.split('.');
let current = data;
for (const key of keys) {
if (current === null || current === undefined) {
return undefined;
}
current = current[key];
}
return current;
}
// 获取默认错误消息
private getDefaultMessage(type: ValidationRuleType, field: string, value?: any): string {
switch (type) {
case ValidationRuleType.REQUIRED:
return `${field} 是必填字段`;
case ValidationRuleType.TYPE:
return `${field} 类型必须是 ${value}`;
case ValidationRuleType.MIN_LENGTH:
return `${field} 最小长度为 ${value}`;
case ValidationRuleType.MAX_LENGTH:
return `${field} 最大长度为 ${value}`;
case ValidationRuleType.MIN_VALUE:
return `${field} 最小值为 ${value}`;
case ValidationRuleType.MAX_VALUE:
return `${field} 最大值为 ${value}`;
case ValidationRuleType.PATTERN:
return `${field} 格式不正确`;
default:
return `${field} 验证失败`;
}
}
// 初始化内置验证器
private initializeBuiltinValidators(): void {
// 必填验证
this.validators.set(ValidationRuleType.REQUIRED, (value: any) => {
return value !== null && value !== undefined && value !== '';
});
// 类型验证
this.validators.set(ValidationRuleType.TYPE, (value: any, expectedType: string) => {
if (value === null || value === undefined) {
return true; // 空值由 required 规则处理
}
switch (expectedType) {
case 'string':
return typeof value === 'string';
case 'number':
return typeof value === 'number' && !isNaN(value);
case 'boolean':
return typeof value === 'boolean';
case 'array':
return Array.isArray(value);
case 'object':
return typeof value === 'object' && !Array.isArray(value);
default:
return true;
}
});
// 最小长度验证
this.validators.set(ValidationRuleType.MIN_LENGTH, (value: any, minLength: number) => {
if (value === null || value === undefined) {
return true;
}
const length = typeof value === 'string' || Array.isArray(value) ? value.length : 0;
return length >= minLength;
});
// 最大长度验证
this.validators.set(ValidationRuleType.MAX_LENGTH, (value: any, maxLength: number) => {
if (value === null || value === undefined) {
return true;
}
const length = typeof value === 'string' || Array.isArray(value) ? value.length : 0;
return length <= maxLength;
});
// 最小值验证
this.validators.set(ValidationRuleType.MIN_VALUE, (value: any, minValue: number) => {
if (value === null || value === undefined) {
return true;
}
return typeof value === 'number' && value >= minValue;
});
// 最大值验证
this.validators.set(ValidationRuleType.MAX_VALUE, (value: any, maxValue: number) => {
if (value === null || value === undefined) {
return true;
}
return typeof value === 'number' && value <= maxValue;
});
// 正则表达式验证
this.validators.set(ValidationRuleType.PATTERN, (value: any, pattern: string | RegExp) => {
if (value === null || value === undefined) {
return true;
}
const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
return regex.test(String(value));
});
}
}
// 验证模式
interface ValidationSchema {
id: string;
name: string;
fields: Record<string, ValidationRule[]>;
}
// 验证配置
interface ValidationConfig {
schemas?: ValidationSchema[];
}
// 验证器函数
type ValidatorFunction = (value: any, ruleValue?: any) => boolean;
6.6 完整使用示例
6.6.1 数据引擎集成示例
// 完整的数据引擎使用示例
class LowCodeDataEngineDemo {
private dataEngine: LowCodeDataEngine;
private bindingManager: DataBindingManager;
constructor() {
// 配置数据引擎
const config: DataEngineConfig = {
state: {
initialState: {
user: {
name: '',
email: '',
age: 0
},
products: [],
cart: {
items: [],
total: 0
}
},
computedProperties: [
{
path: 'cart.total',
dependencies: ['cart.items'],
computer: (items: any[]) => {
return items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
}
}
]
},
dataSources: [
{
id: 'api',
name: 'Main API',
type: DataSourceType.REST_API,
baseURL: 'https://api.example.com',
headers: {
'Content-Type': 'application/json'
},
timeout: 10000
} as RestApiConfig
],
transforms: [
{
id: 'product_filter',
name: '产品过滤',
type: TransformType.FILTER,
input: { source: 'api', path: 'products' },
output: { target: 'state', path: 'products' },
parameters: {
predicate: (product: any) => product.available === true
}
}
],
validation: {
schemas: [
{
id: 'user_schema',
name: '用户验证',
fields: {
'name': [
{ type: ValidationRuleType.REQUIRED, message: '姓名不能为空' },
{ type: ValidationRuleType.MIN_LENGTH, value: 2, message: '姓名至少2个字符' }
],
'email': [
{ type: ValidationRuleType.REQUIRED, message: '邮箱不能为空' },
{ type: ValidationRuleType.PATTERN, value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, message: '邮箱格式不正确' }
],
'age': [
{ type: ValidationRuleType.REQUIRED, message: '年龄不能为空' },
{ type: ValidationRuleType.MIN_VALUE, value: 0, message: '年龄不能小于0' },
{ type: ValidationRuleType.MAX_VALUE, value: 150, message: '年龄不能大于150' }
]
}
}
]
},
cache: {
strategy: CacheStrategy.LRU,
maxSize: 1000,
defaultTTL: 300000
}
};
// 创建数据引擎
this.dataEngine = new LowCodeDataEngine(config);
this.bindingManager = new DataBindingManager(this.dataEngine.bindingEngine);
}
async initialize(): Promise<void> {
// 启动数据引擎
await this.dataEngine.start();
// 创建数据绑定
this.setupDataBindings();
// 设置事件监听
this.setupEventListeners();
console.log('数据引擎演示初始化完成');
}
private setupDataBindings(): void {
// 创建用户名绑定
const nameBindingId = this.bindingManager.createBuilder()
.from('form', 'user.name')
.to('state', 'user.name')
.type(BindingType.TWO_WAY)
.validate((value, context) => {
return typeof value === 'string' && value.length >= 2;
})
.build();
// 创建购物车总价绑定
const totalBindingId = this.bindingManager.createBuilder()
.from('state', 'cart.total')
.to('ui', 'cart.totalDisplay')
.type(BindingType.ONE_WAY)
.transform((value) => `¥${value.toFixed(2)}`)
.build();
// 创建绑定组
this.bindingManager.createGroup('user_form');
this.bindingManager.addToGroup('user_form', nameBindingId);
this.bindingManager.createGroup('cart_display');
this.bindingManager.addToGroup('cart_display', totalBindingId);
}
private setupEventListeners(): void {
// 监听状态变化
this.dataEngine.stateManager.subscribe('user', (newValue, oldValue) => {
console.log('用户信息变化:', { newValue, oldValue });
});
// 监听数据绑定事件
this.dataEngine.bindingEngine.eventBus.on('binding:synced', (event) => {
console.log('数据绑定同步:', event);
});
// 监听数据源查询事件
this.dataEngine.dataSourceManager.eventBus.on('datasource:queried', (event) => {
console.log('数据源查询:', event);
});
}
// 演示用户操作
async demonstrateUserOperations(): Promise<void> {
console.log('=== 演示用户操作 ===');
// 更新用户信息
this.dataEngine.stateManager.setState('user.name', 'John Doe');
this.dataEngine.stateManager.setState('user.email', 'john@example.com');
this.dataEngine.stateManager.setState('user.age', 30);
// 验证用户数据
const userValidation = this.dataEngine.validationEngine.validate('user_schema',
this.dataEngine.stateManager.getState('user')
);
console.log('用户验证结果:', userValidation);
// 添加购物车商品
const cartItems = [
{ id: 1, name: '商品1', price: 100, quantity: 2 },
{ id: 2, name: '商品2', price: 50, quantity: 1 }
];
this.dataEngine.stateManager.setState('cart.items', cartItems);
// 查看计算属性(总价)
const total = this.dataEngine.stateManager.getState('cart.total');
console.log('购物车总价:', total);
}
// 演示数据源操作
async demonstrateDataSourceOperations(): Promise<void> {
console.log('=== 演示数据源操作 ===');
try {
// 查询产品列表
const productsResult = await this.dataEngine.dataSourceManager.query('api', {
method: 'GET',
endpoint: '/products',
params: { category: 'electronics' }
});
console.log('产品查询结果:', productsResult);
// 应用数据变换
if (productsResult.data) {
const transformResult = await this.dataEngine.transformEngine.transform(
'product_filter',
productsResult.data
);
console.log('产品过滤结果:', transformResult);
// 更新状态
if (transformResult.success) {
this.dataEngine.stateManager.setState('products', transformResult.data);
}
}
} catch (error) {
console.error('数据源操作失败:', error);
}
}
// 演示缓存操作
demonstrateCacheOperations(): void {
console.log('=== 演示缓存操作 ===');
const cache = this.dataEngine.cacheManager;
// 设置缓存
cache.set('user_preferences', { theme: 'dark', language: 'zh-CN' });
cache.set('recent_searches', ['低代码', '可视化', '数据绑定']);
// 获取缓存
const preferences = cache.get('user_preferences');
const searches = cache.get('recent_searches');
console.log('用户偏好:', preferences);
console.log('最近搜索:', searches);
// 查看缓存统计
const stats = cache.getStats();
console.log('缓存统计:', stats);
}
async destroy(): Promise<void> {
await this.dataEngine.stop();
console.log('数据引擎演示已停止');
}
}
// 使用示例
async function runDataEngineDemo() {
const demo = new LowCodeDataEngineDemo();
try {
await demo.initialize();
await demo.demonstrateUserOperations();
await demo.demonstrateDataSourceOperations();
demo.demonstrateCacheOperations();
} catch (error) {
console.error('演示运行失败:', error);
} finally {
await demo.destroy();
}
}
// 运行演示
// runDataEngineDemo();
6.7 本章小结
本章详细介绍了低代码平台数据引擎与状态管理系统的设计与实现。我们构建了一个完整的数据处理基础设施,包括以下核心组件:
核心要点
数据引擎架构
- 模块化设计,各组件职责清晰
- 事件驱动架构,支持松耦合通信
- 统一的配置管理和生命周期管理
状态管理系统
- 响应式状态管理,支持订阅模式
- 计算属性自动更新机制
- 动作和变更的统一管理
- 状态持久化支持
数据源管理
- 多种数据源类型支持(REST API、GraphQL等)
- 统一的查询接口和错误处理
- 连接池和健康检查机制
数据绑定引擎
- 单向、双向、一次性绑定支持
- 表达式编译和依赖追踪
- 循环绑定检测和防护
- 绑定分组管理
数据变换引擎
- 内置常用变换操作(map、filter、sort等)
- 可扩展的自定义变换支持
- 批量变换和错误处理
数据验证引擎
- 丰富的内置验证规则
- 自定义验证器支持
- 详细的错误信息和字段级验证
数据缓存管理
- 多种缓存策略(LRU、LFU、TTL、FIFO)
- 自动过期清理机制
- 缓存统计和监控
技术特色
- 高性能:优化的数据结构和算法,支持大规模数据处理
- 可扩展:插件化架构,易于扩展新功能
- 类型安全:完整的TypeScript类型定义
- 错误处理:完善的错误捕获和恢复机制
- 监控支持:详细的事件和统计信息
最佳实践
- 状态设计:保持状态结构扁平化,避免深层嵌套
- 绑定管理:合理使用绑定类型,避免不必要的双向绑定
- 缓存策略:根据数据特性选择合适的缓存策略
- 验证规则:在客户端和服务端都进行数据验证
- 错误处理:提供友好的错误提示和恢复机制
下一章我们将学习表单引擎与动态表单,了解如何基于数据引擎构建强大的表单系统。
6.3 数据源管理系统
6.3.1 数据源管理器
// 数据源接口
interface DataSource {
id: string;
name: string;
type: DataSourceType;
config: DataSourceConfig;
connect(): Promise<void>;
disconnect(): Promise<void>;
query(params: QueryParams): Promise<QueryResult>;
isConnected(): boolean;
}
// 数据源类型
enum DataSourceType {
REST_API = 'rest_api',
GRAPHQL = 'graphql',
WEBSOCKET = 'websocket',
DATABASE = 'database',
MOCK = 'mock',
STATIC = 'static'
}
// 查询参数
interface QueryParams {
method?: string;
endpoint?: string;
params?: Record<string, any>;
headers?: Record<string, string>;
body?: any;
timeout?: number;
}
// 查询结果
interface QueryResult {
data: any;
status: number;
headers?: Record<string, string>;
error?: string;
timestamp: number;
}
// REST API 数据源
class RestApiDataSource implements DataSource {
public id: string;
public name: string;
public type = DataSourceType.REST_API;
public config: RestApiConfig;
private baseURL: string;
private defaultHeaders: Record<string, string>;
private timeout: number;
private connected: boolean = false;
constructor(id: string, name: string, config: RestApiConfig) {
this.id = id;
this.name = name;
this.config = config;
this.baseURL = config.baseURL;
this.defaultHeaders = config.headers || {};
this.timeout = config.timeout || 10000;
}
async connect(): Promise<void> {
try {
// 测试连接
if (this.config.healthCheckEndpoint) {
await this.query({
method: 'GET',
endpoint: this.config.healthCheckEndpoint,
timeout: 5000
});
}
this.connected = true;
console.log(`REST API 数据源连接成功: ${this.name}`);
} catch (error) {
this.connected = false;
throw new Error(`REST API 数据源连接失败: ${error}`);
}
}
async disconnect(): Promise<void> {
this.connected = false;
console.log(`REST API 数据源已断开: ${this.name}`);
}
async query(params: QueryParams): Promise<QueryResult> {
const url = this.buildURL(params.endpoint || '');
const headers = { ...this.defaultHeaders, ...params.headers };
const timeout = params.timeout || this.timeout;
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
const response = await fetch(url, {
method: params.method || 'GET',
headers,
body: params.body ? JSON.stringify(params.body) : undefined,
signal: controller.signal
});
clearTimeout(timeoutId);
const data = await response.json();
return {
data,
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
timestamp: Date.now()
};
} catch (error) {
return {
data: null,
status: 0,
error: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
}
isConnected(): boolean {
return this.connected;
}
private buildURL(endpoint: string): string {
if (endpoint.startsWith('http')) {
return endpoint;
}
const baseURL = this.baseURL.endsWith('/') ? this.baseURL.slice(0, -1) : this.baseURL;
const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
return `${baseURL}${path}`;
}
}
// GraphQL 数据源
class GraphQLDataSource implements DataSource {
public id: string;
public name: string;
public type = DataSourceType.GRAPHQL;
public config: GraphQLConfig;
private endpoint: string;
private headers: Record<string, string>;
private connected: boolean = false;
constructor(id: string, name: string, config: GraphQLConfig) {
this.id = id;
this.name = name;
this.config = config;
this.endpoint = config.endpoint;
this.headers = config.headers || {};
}
async connect(): Promise<void> {
try {
// 测试 GraphQL 连接
await this.query({
body: {
query: '{ __schema { types { name } } }'
}
});
this.connected = true;
console.log(`GraphQL 数据源连接成功: ${this.name}`);
} catch (error) {
this.connected = false;
throw new Error(`GraphQL 数据源连接失败: ${error}`);
}
}
async disconnect(): Promise<void> {
this.connected = false;
console.log(`GraphQL 数据源已断开: ${this.name}`);
}
async query(params: QueryParams): Promise<QueryResult> {
try {
const response = await fetch(this.endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...this.headers,
...params.headers
},
body: JSON.stringify(params.body)
});
const data = await response.json();
return {
data,
status: response.status,
timestamp: Date.now()
};
} catch (error) {
return {
data: null,
status: 0,
error: error instanceof Error ? error.message : String(error),
timestamp: Date.now()
};
}
}
isConnected(): boolean {
return this.connected;
}
}
// 数据源管理器
class DataSourceManager {
private dataSources: Map<string, DataSource> = new Map();
private eventBus: EventBus;
private config: DataSourceConfig[];
constructor(eventBus: EventBus, config: DataSourceConfig[]) {
this.eventBus = eventBus;
this.config = config;
}
async initialize(): Promise<void> {
// 初始化所有数据源
for (const config of this.config) {
await this.createDataSource(config);
}
console.log('数据源管理器初始化完成');
}
async createDataSource(config: DataSourceConfig): Promise<DataSource> {
let dataSource: DataSource;
switch (config.type) {
case DataSourceType.REST_API:
dataSource = new RestApiDataSource(config.id, config.name, config as RestApiConfig);
break;
case DataSourceType.GRAPHQL:
dataSource = new GraphQLDataSource(config.id, config.name, config as GraphQLConfig);
break;
default:
throw new Error(`不支持的数据源类型: ${config.type}`);
}
// 连接数据源
await dataSource.connect();
// 注册数据源
this.dataSources.set(config.id, dataSource);
// 发送事件
this.eventBus.emit('datasource:created', {
id: config.id,
name: config.name,
type: config.type
});
return dataSource;
}
getDataSource(id: string): DataSource | undefined {
return this.dataSources.get(id);
}
getAllDataSources(): DataSource[] {
return Array.from(this.dataSources.values());
}
async removeDataSource(id: string): Promise<void> {
const dataSource = this.dataSources.get(id);
if (dataSource) {
await dataSource.disconnect();
this.dataSources.delete(id);
this.eventBus.emit('datasource:removed', { id });
}
}
async query(dataSourceId: string, params: QueryParams): Promise<QueryResult> {
const dataSource = this.dataSources.get(dataSourceId);
if (!dataSource) {
throw new Error(`数据源未找到: ${dataSourceId}`);
}
if (!dataSource.isConnected()) {
await dataSource.connect();
}
const result = await dataSource.query(params);
// 发送查询事件
this.eventBus.emit('datasource:queried', {
dataSourceId,
params,
result,
timestamp: Date.now()
});
return result;
}
async destroy(): Promise<void> {
// 断开所有数据源连接
for (const dataSource of this.dataSources.values()) {
await dataSource.disconnect();
}
this.dataSources.clear();
console.log('数据源管理器已销毁');
}
}
// 数据源配置接口
interface DataSourceConfig {
id: string;
name: string;
type: DataSourceType;
}
interface RestApiConfig extends DataSourceConfig {
baseURL: string;
headers?: Record<string, string>;
timeout?: number;
healthCheckEndpoint?: string;
}
interface GraphQLConfig extends DataSourceConfig {
endpoint: string;
headers?: Record<string, string>;
}
6.3.2 数据缓存管理
// 缓存策略
enum CacheStrategy {
LRU = 'lru',
LFU = 'lfu',
TTL = 'ttl',
FIFO = 'fifo'
}
// 缓存项
interface CacheItem {
key: string;
value: any;
timestamp: number;
ttl?: number;
accessCount: number;
lastAccessed: number;
}
// 数据缓存管理器
class DataCacheManager {
private cache: Map<string, CacheItem> = new Map();
private strategy: CacheStrategy;
private maxSize: number;
private defaultTTL: number;
private cleanupInterval: number;
private cleanupTimer?: NodeJS.Timeout;
constructor(config: CacheConfig) {
this.strategy = config.strategy || CacheStrategy.LRU;
this.maxSize = config.maxSize || 1000;
this.defaultTTL = config.defaultTTL || 300000; // 5分钟
this.cleanupInterval = config.cleanupInterval || 60000; // 1分钟
this.startCleanup();
}
set(key: string, value: any, ttl?: number): void {
const now = Date.now();
const item: CacheItem = {
key,
value,
timestamp: now,
ttl: ttl || this.defaultTTL,
accessCount: 1,
lastAccessed: now
};
// 检查缓存大小限制
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
this.evict();
}
this.cache.set(key, item);
}
get(key: string): any {
const item = this.cache.get(key);
if (!item) {
return undefined;
}
// 检查TTL
if (this.isExpired(item)) {
this.cache.delete(key);
return undefined;
}
// 更新访问信息
item.accessCount++;
item.lastAccessed = Date.now();
return item.value;
}
has(key: string): boolean {
const item = this.cache.get(key);
if (!item) {
return false;
}
if (this.isExpired(item)) {
this.cache.delete(key);
return false;
}
return true;
}
delete(key: string): boolean {
return this.cache.delete(key);
}
clear(): void {
this.cache.clear();
}
size(): number {
return this.cache.size;
}
// 获取缓存统计信息
getStats(): CacheStats {
const items = Array.from(this.cache.values());
const now = Date.now();
return {
size: this.cache.size,
maxSize: this.maxSize,
hitRate: this.calculateHitRate(),
expiredCount: items.filter(item => this.isExpired(item)).length,
averageAge: items.reduce((sum, item) => sum + (now - item.timestamp), 0) / items.length || 0
};
}
private isExpired(item: CacheItem): boolean {
if (!item.ttl) {
return false;
}
return Date.now() - item.timestamp > item.ttl;
}
private evict(): void {
switch (this.strategy) {
case CacheStrategy.LRU:
this.evictLRU();
break;
case CacheStrategy.LFU:
this.evictLFU();
break;
case CacheStrategy.FIFO:
this.evictFIFO();
break;
default:
this.evictLRU();
}
}
private evictLRU(): void {
let oldestKey = '';
let oldestTime = Date.now();
for (const [key, item] of this.cache) {
if (item.lastAccessed < oldestTime) {
oldestTime = item.lastAccessed;
oldestKey = key;
}
}
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
private evictLFU(): void {
let leastUsedKey = '';
let leastCount = Infinity;
for (const [key, item] of this.cache) {
if (item.accessCount < leastCount) {
leastCount = item.accessCount;
leastUsedKey = key;
}
}
if (leastUsedKey) {
this.cache.delete(leastUsedKey);
}
}
private evictFIFO(): void {
let oldestKey = '';
let oldestTime = Date.now();
for (const [key, item] of this.cache) {
if (item.timestamp < oldestTime) {
oldestTime = item.timestamp;
oldestKey = key;
}
}
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
private calculateHitRate(): number {
// 这里需要实际的命中率统计逻辑
// 简化实现,实际应该记录命中和未命中次数
return 0.85; // 示例值
}
private startCleanup(): void {
this.cleanupTimer = setInterval(() => {
this.cleanup();
}, this.cleanupInterval);
}
private cleanup(): void {
const now = Date.now();
const expiredKeys: string[] = [];
for (const [key, item] of this.cache) {
if (this.isExpired(item)) {
expiredKeys.push(key);
}
}
expiredKeys.forEach(key => this.cache.delete(key));
if (expiredKeys.length > 0) {
console.log(`清理过期缓存项: ${expiredKeys.length} 个`);
}
}
destroy(): void {
if (this.cleanupTimer) {
clearInterval(this.cleanupTimer);
}
this.cache.clear();
console.log('数据缓存管理器已销毁');
}
}
// 缓存配置
interface CacheConfig {
strategy?: CacheStrategy;
maxSize?: number;
defaultTTL?: number;
cleanupInterval?: number;
}
// 缓存统计信息
interface CacheStats {
size: number;
maxSize: number;
hitRate: number;
expiredCount: number;
averageAge: number;
}
```typescript
// 数据引擎核心接口
interface DataEngine {
// 状态管理
stateManager: StateManager;
// 数据源管理
dataSourceManager: DataSourceManager;
// 数据绑定引擎
bindingEngine: DataBindingEngine;
// 数据变换引擎
transformEngine: DataTransformEngine;
// 数据验证引擎
validationEngine: DataValidationEngine;
// 数据缓存管理
cacheManager: DataCacheManager;
}
// 数据引擎实现
class LowCodeDataEngine implements DataEngine {
public stateManager: StateManager;
public dataSourceManager: DataSourceManager;
public bindingEngine: DataBindingEngine;
public transformEngine: DataTransformEngine;
public validationEngine: DataValidationEngine;
public cacheManager: DataCacheManager;
private eventBus: EventBus;
private config: DataEngineConfig;
constructor(config: DataEngineConfig) {
this.config = config;
this.eventBus = new EventBus();
// 初始化各个子系统
this.initializeSubSystems();
}
private initializeSubSystems(): void {
this.stateManager = new StateManager(this.eventBus, this.config.state);
this.dataSourceManager = new DataSourceManager(this.eventBus, this.config.dataSources);
this.bindingEngine = new DataBindingEngine(this.eventBus, this.stateManager);
this.transformEngine = new DataTransformEngine(this.config.transforms);
this.validationEngine = new DataValidationEngine(this.config.validation);
this.cacheManager = new DataCacheManager(this.config.cache);
}
// 启动数据引擎
async start(): Promise<void> {
await this.dataSourceManager.initialize();
await this.stateManager.initialize();
await this.bindingEngine.initialize();
console.log('数据引擎启动完成');
}
// 停止数据引擎
async stop(): Promise<void> {
await this.bindingEngine.destroy();
await this.stateManager.destroy();
await this.dataSourceManager.destroy();
console.log('数据引擎已停止');
}
}
// 数据引擎配置
interface DataEngineConfig {
state: StateManagerConfig;
dataSources: DataSourceConfig[];
transforms: TransformConfig[];
validation: ValidationConfig;
cache: CacheConfig;
}
6.1.2 事件总线系统
// 事件总线接口
interface EventBus {
on(event: string, handler: Function): void;
off(event: string, handler: Function): void;
emit(event: string, data?: any): void;
once(event: string, handler: Function): void;
}
// 事件总线实现
class EventBus implements EventBus {
private listeners: Map<string, Set<Function>> = new Map();
private onceListeners: Map<string, Set<Function>> = new Map();
on(event: string, handler: Function): void {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event)!.add(handler);
}
off(event: string, handler: Function): void {
const handlers = this.listeners.get(event);
if (handlers) {
handlers.delete(handler);
if (handlers.size === 0) {
this.listeners.delete(event);
}
}
}
emit(event: string, data?: any): void {
// 处理普通监听器
const handlers = this.listeners.get(event);
if (handlers) {
handlers.forEach(handler => {
try {
handler(data);
} catch (error) {
console.error(`事件处理器执行失败: ${event}`, error);
}
});
}
// 处理一次性监听器
const onceHandlers = this.onceListeners.get(event);
if (onceHandlers) {
onceHandlers.forEach(handler => {
try {
handler(data);
} catch (error) {
console.error(`一次性事件处理器执行失败: ${event}`, error);
}
});
this.onceListeners.delete(event);
}
}
once(event: string, handler: Function): void {
if (!this.onceListeners.has(event)) {
this.onceListeners.set(event, new Set());
}
this.onceListeners.get(event)!.add(handler);
}
// 清除所有监听器
clear(): void {
this.listeners.clear();
this.onceListeners.clear();
}
// 获取事件统计信息
getStats(): { [event: string]: number } {
const stats: { [event: string]: number } = {};
this.listeners.forEach((handlers, event) => {
stats[event] = handlers.size;
});
return stats;
}
}
6.2 状态管理系统
6.2.1 状态管理器核心
// 状态管理器接口
interface StateManager {
getState(path?: string): any;
setState(path: string, value: any): void;
updateState(path: string, updater: (current: any) => any): void;
subscribe(path: string, callback: StateChangeCallback): () => void;
createComputed(path: string, dependencies: string[], computer: ComputedFunction): void;
createAction(name: string, action: ActionFunction): void;
}
// 状态变化回调
type StateChangeCallback = (newValue: any, oldValue: any, path: string) => void;
// 计算属性函数
type ComputedFunction = (...dependencies: any[]) => any;
// 动作函数
type ActionFunction = (context: ActionContext, ...args: any[]) => any;
// 动作上下文
interface ActionContext {
getState: (path?: string) => any;
setState: (path: string, value: any) => void;
updateState: (path: string, updater: (current: any) => any) => void;
commit: (mutation: string, payload?: any) => void;
dispatch: (action: string, payload?: any) => Promise<any>;
}
// 状态管理器实现
class StateManager implements StateManager {
private state: any = {};
private subscribers: Map<string, Set<StateChangeCallback>> = new Map();
private computedProperties: Map<string, ComputedProperty> = new Map();
private actions: Map<string, ActionFunction> = new Map();
private mutations: Map<string, MutationFunction> = new Map();
private eventBus: EventBus;
private config: StateManagerConfig;
constructor(eventBus: EventBus, config: StateManagerConfig) {
this.eventBus = eventBus;
this.config = config;
this.state = config.initialState || {};
}
async initialize(): Promise<void> {
// 初始化计算属性
this.initializeComputedProperties();
// 注册内置动作
this.registerBuiltinActions();
console.log('状态管理器初始化完成');
}
getState(path?: string): any {
if (!path) {
return this.state;
}
return this.getValueByPath(this.state, path);
}
setState(path: string, value: any): void {
const oldValue = this.getValueByPath(this.state, path);
if (oldValue === value) {
return; // 值未变化,不触发更新
}
this.setValueByPath(this.state, path, value);
// 触发订阅者
this.notifySubscribers(path, value, oldValue);
// 更新计算属性
this.updateComputedProperties(path);
// 发送状态变化事件
this.eventBus.emit('state:changed', {
path,
newValue: value,
oldValue,
timestamp: Date.now()
});
}
updateState(path: string, updater: (current: any) => any): void {
const currentValue = this.getValueByPath(this.state, path);
const newValue = updater(currentValue);
this.setState(path, newValue);
}
subscribe(path: string, callback: StateChangeCallback): () => void {
if (!this.subscribers.has(path)) {
this.subscribers.set(path, new Set());
}
this.subscribers.get(path)!.add(callback);
// 返回取消订阅函数
return () => {
const callbacks = this.subscribers.get(path);
if (callbacks) {
callbacks.delete(callback);
if (callbacks.size === 0) {
this.subscribers.delete(path);
}
}
};
}
createComputed(path: string, dependencies: string[], computer: ComputedFunction): void {
const computedProperty: ComputedProperty = {
path,
dependencies,
computer,
value: undefined,
isValid: false
};
this.computedProperties.set(path, computedProperty);
// 订阅依赖项变化
dependencies.forEach(dep => {
this.subscribe(dep, () => {
this.invalidateComputed(path);
});
});
// 初始计算
this.computeProperty(computedProperty);
}
createAction(name: string, action: ActionFunction): void {
this.actions.set(name, action);
}
// 执行动作
async dispatch(actionName: string, payload?: any): Promise<any> {
const action = this.actions.get(actionName);
if (!action) {
throw new Error(`动作未找到: ${actionName}`);
}
const context: ActionContext = {
getState: this.getState.bind(this),
setState: this.setState.bind(this),
updateState: this.updateState.bind(this),
commit: this.commit.bind(this),
dispatch: this.dispatch.bind(this)
};
try {
const result = await action(context, payload);
this.eventBus.emit('action:executed', {
actionName,
payload,
result,
timestamp: Date.now()
});
return result;
} catch (error) {
this.eventBus.emit('action:error', {
actionName,
payload,
error,
timestamp: Date.now()
});
throw error;
}
}
// 提交变更
commit(mutationName: string, payload?: any): void {
const mutation = this.mutations.get(mutationName);
if (!mutation) {
throw new Error(`变更未找到: ${mutationName}`);
}
const oldState = JSON.parse(JSON.stringify(this.state));
mutation(this.state, payload);
this.eventBus.emit('mutation:committed', {
mutationName,
payload,
oldState,
newState: this.state,
timestamp: Date.now()
});
}
// 私有方法
private getValueByPath(obj: any, path: string): any {
const keys = path.split('.');
let current = obj;
for (const key of keys) {
if (current === null || current === undefined) {
return undefined;
}
current = current[key];
}
return current;
}
private setValueByPath(obj: any, path: string, value: any): void {
const keys = path.split('.');
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (!(key in current) || typeof current[key] !== 'object') {
current[key] = {};
}
current = current[key];
}
current[keys[keys.length - 1]] = value;
}
private notifySubscribers(path: string, newValue: any, oldValue: any): void {
const callbacks = this.subscribers.get(path);
if (callbacks) {
callbacks.forEach(callback => {
try {
callback(newValue, oldValue, path);
} catch (error) {
console.error(`状态订阅回调执行失败: ${path}`, error);
}
});
}
}
private initializeComputedProperties(): void {
// 从配置中初始化计算属性
if (this.config.computedProperties) {
this.config.computedProperties.forEach(computed => {
this.createComputed(computed.path, computed.dependencies, computed.computer);
});
}
}
private registerBuiltinActions(): void {
// 注册内置动作
this.createAction('reset', (context) => {
context.setState('', this.config.initialState || {});
});
this.createAction('merge', (context, payload) => {
const currentState = context.getState();
const newState = { ...currentState, ...payload };
context.setState('', newState);
});
}
private updateComputedProperties(changedPath: string): void {
this.computedProperties.forEach((computed, path) => {
if (computed.dependencies.some(dep => changedPath.startsWith(dep))) {
this.invalidateComputed(path);
}
});
}
private invalidateComputed(path: string): void {
const computed = this.computedProperties.get(path);
if (computed) {
computed.isValid = false;
this.computeProperty(computed);
}
}
private computeProperty(computed: ComputedProperty): void {
try {
const dependencies = computed.dependencies.map(dep => this.getValueByPath(this.state, dep));
const newValue = computed.computer(...dependencies);
if (computed.value !== newValue) {
const oldValue = computed.value;
computed.value = newValue;
computed.isValid = true;
// 设置计算属性值到状态中
this.setValueByPath(this.state, computed.path, newValue);
// 通知订阅者
this.notifySubscribers(computed.path, newValue, oldValue);
}
} catch (error) {
console.error(`计算属性计算失败: ${computed.path}`, error);
}
}
async destroy(): Promise<void> {
this.subscribers.clear();
this.computedProperties.clear();
this.actions.clear();
this.mutations.clear();
console.log('状态管理器已销毁');
}
}
// 计算属性接口
interface ComputedProperty {
path: string;
dependencies: string[];
computer: ComputedFunction;
value: any;
isValid: boolean;
}
// 变更函数
type MutationFunction = (state: any, payload?: any) => void;
// 状态管理器配置
interface StateManagerConfig {
initialState?: any;
computedProperties?: {
path: string;
dependencies: string[];
computer: ComputedFunction;
}[];
enableDevtools?: boolean;
enableTimeTravel?: boolean;
}
6.2.2 状态持久化
// 状态持久化接口
interface StatePersistence {
save(state: any): Promise<void>;
load(): Promise<any>;
clear(): Promise<void>;
}
// 本地存储持久化
class LocalStoragePersistence implements StatePersistence {
private key: string;
constructor(key: string = 'lowcode-state') {
this.key = key;
}
async save(state: any): Promise<void> {
try {
const serialized = JSON.stringify(state);
localStorage.setItem(this.key, serialized);
} catch (error) {
console.error('状态保存失败:', error);
throw error;
}
}
async load(): Promise<any> {
try {
const serialized = localStorage.getItem(this.key);
return serialized ? JSON.parse(serialized) : null;
} catch (error) {
console.error('状态加载失败:', error);
return null;
}
}
async clear(): Promise<void> {
localStorage.removeItem(this.key);
}
}
// IndexedDB 持久化
class IndexedDBPersistence implements StatePersistence {
private dbName: string;
private storeName: string;
private version: number;
constructor(dbName: string = 'lowcode-db', storeName: string = 'state', version: number = 1) {
this.dbName = dbName;
this.storeName = storeName;
this.version = version;
}
private async openDB(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result);
request.onupgradeneeded = (event) => {
const db = (event.target as IDBOpenDBRequest).result;
if (!db.objectStoreNames.contains(this.storeName)) {
db.createObjectStore(this.storeName);
}
};
});
}
async save(state: any): Promise<void> {
const db = await this.openDB();
const transaction = db.transaction([this.storeName], 'readwrite');
const store = transaction.objectStore(this.storeName);
return new Promise((resolve, reject) => {
const request = store.put(state, 'current');
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve();
});
}
async load(): Promise<any> {
const db = await this.openDB();
const transaction = db.transaction([this.storeName], 'readonly');
const store = transaction.objectStore(this.storeName);
return new Promise((resolve, reject) => {
const request = store.get('current');
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve(request.result || null);
});
}
async clear(): Promise<void> {
const db = await this.openDB();
const transaction = db.transaction([this.storeName], 'readwrite');
const store = transaction.objectStore(this.storeName);
return new Promise((resolve, reject) => {
const request = store.delete('current');
request.onerror = () => reject(request.error);
request.onsuccess = () => resolve();
});
}
}
// 持久化状态管理器
class PersistentStateManager extends StateManager {
private persistence: StatePersistence;
private autoSave: boolean;
private saveDebounceTime: number;
private saveTimer?: NodeJS.Timeout;
constructor(
eventBus: EventBus,
config: StateManagerConfig & { persistence?: StatePersistence; autoSave?: boolean; saveDebounceTime?: number }
) {
super(eventBus, config);
this.persistence = config.persistence || new LocalStoragePersistence();
this.autoSave = config.autoSave !== false;
this.saveDebounceTime = config.saveDebounceTime || 1000;
if (this.autoSave) {
this.setupAutoSave();
}
}
async initialize(): Promise<void> {
// 加载持久化状态
await this.loadPersistedState();
// 调用父类初始化
await super.initialize();
}
private async loadPersistedState(): Promise<void> {
try {
const persistedState = await this.persistence.load();
if (persistedState) {
this.state = { ...this.state, ...persistedState };
console.log('持久化状态加载完成');
}
} catch (error) {
console.error('持久化状态加载失败:', error);
}
}
private setupAutoSave(): void {
this.eventBus.on('state:changed', () => {
this.debouncedSave();
});
}
private debouncedSave(): void {
if (this.saveTimer) {
clearTimeout(this.saveTimer);
}
this.saveTimer = setTimeout(() => {
this.saveState();
}, this.saveDebounceTime);
}
async saveState(): Promise<void> {
try {
await this.persistence.save(this.state);
console.log('状态保存完成');
} catch (error) {
console.error('状态保存失败:', error);
}
}
async clearPersistedState(): Promise<void> {
await this.persistence.clear();
console.log('持久化状态已清除');
}
async destroy(): Promise<void> {
if (this.saveTimer) {
clearTimeout(this.saveTimer);
}
// 最后保存一次状态
if (this.autoSave) {
await this.saveState();
}
await super.destroy();
}
}