一个强大的、类型安全的数据模型管理库,支持同步和异步数据验证、依赖反应、脏数据管理和统一错误处理。
model-reaction
是一个用于管理应用程序数据模型的 TypeScript 库,提供以下核心功能:
- 数据验证:支持同步和异步验证规则,支持自定义验证消息
- 依赖反应:当指定字段变化时,自动触发相关计算和操作
- 脏数据管理:跟踪验证失败的数据,并提供清除功能
- 事件系统:支持订阅字段变化、验证完成和错误事件
- 错误处理:统一的错误处理机制,支持错误类型分类和自定义错误监听
- 类型安全:完全基于 TypeScript 构建,提供良好的类型提示
# 使用 npm
npm install model-reaction
# 使用 yarn
yarn add model-reaction
import { ModelManager, Model, ValidationRules } from 'model-reaction';
import { ErrorType } from 'model-reaction/error-handler';
// 定义模型架构
const userModel = new ModelManager({
name: {
type: 'string',
validator: [
ValidationRules.required.withMessage('姓名不能为空'),
ValidationRules.minLength(2).withMessage('姓名长度不能少于2个字符')
],
default: '',
},
age: {
type: 'number',
validator: [
ValidationRules.required.withMessage('年龄不能为空'),
ValidationRules.number.withMessage('年龄必须是数字'),
ValidationRules.min(18).withMessage('年龄必须大于等于18岁')
],
default: 18
},
info: {
type: 'string',
reaction: {
fields: ['name', 'age'],
computed: (values) => `My name is ${values.name} and I am ${values.age} years old.`,
action: (values) => console.log('Info updated:', values.computed)
},
default: ''
}
}, {
debounceReactions: 100,
asyncValidationTimeout: 5000
});
// 订阅错误事件
userModel.on('validation:error', (error) => {
console.error(`验证错误: ${error.field} - ${error.message}`);
});
userModel.on('field:not-found', (error) => {
console.error(`字段不存在: ${error.field}`);
});
// 设置字段值
await userModel.setField('name', 'John');
await userModel.setField('age', 30);
// 尝试设置不存在的字段
await userModel.setField('nonexistentField', 'value');
// 获取字段值
console.log('姓名:', userModel.getField('name')); // 输出: John
console.log('年龄:', userModel.getField('age')); // 输出: 30
console.log('信息:', userModel.getField('info')); // 输出: My name is John and I am 30 years old.
// 验证所有字段
const isValid = await userModel.validateAll();
console.log('验证是否通过:', isValid);
console.log('验证错误:', userModel.validationErrors);
console.log('验证摘要:', userModel.getValidationSummary());
// 获取脏数据
console.log('脏数据:', userModel.getDirtyData());
// 清除脏数据
userModel.clearDirtyData();
console.log('清除后脏数据:', userModel.getDirtyData());
import { ModelManager, Model, ValidationRules } from 'model-reaction';
// 定义模型架构
const asyncUserModel = new ModelManager({
name: {
type: 'string',
validator: [ValidationRules.required.withMessage('用户名不能为空')],
default: '',
},
username: {
type: 'string',
validator: [
ValidationRules.required.withMessage('账号不能为空'),
ValidationRules.asyncUnique(
async (value: string): Promise<boolean> => {
// 模拟异步检查用户名是否已存在
return new Promise<boolean>((resolve) => {
setTimeout(() => {
// 假设 'admin' 已被占用
resolve(value !== 'admin');
}, 100);
});
}
).withMessage('用户名已存在')
],
default: ''
}
}, {
asyncValidationTimeout: 3000
});
// 异步设置字段值
const result1 = await asyncUserModel.setField('username', 'newuser');
console.log('设置新用户名结果:', result1); // 输出: true
const result2 = await asyncUserModel.setField('username', 'admin');
console.log('设置已存在用户名结果:', result2); // 输出: false
console.log('验证错误:', asyncUserModel.validationErrors);
console.log('脏数据:', asyncUserModel.getDirtyData());
模型管理器是库的核心类,提供以下方法:
new ModelManager(schema: Model, options?: ModelOptions);
setField(field: string, value: any): Promise<boolean>
: 设置单个字段值,返回验证结果setFields(fields: Record<string, any>): Promise<boolean>
: 批量设置字段值,返回验证结果getField(field: string): any
: 获取字段值validateAll(): Promise<boolean>
: 验证所有字段,返回整体验证结果getValidationSummary(): string
: 获取验证摘要信息getDirtyData(): Record<string, any>
: 获取验证失败的脏数据clearDirtyData(): void
: 清除所有脏数据on(event: string, callback: (data: any) => void): void
: 订阅事件off(event: string, callback?: (data: any) => void): void
: 取消订阅事件emit(event: string, data: any): void
: 触发事件
field:change
: 字段值变化时触发validation:complete
: 验证完成时触发validation:error
: 验证错误时触发reaction:error
: 反应处理错误时触发field:not-found
: 尝试访问不存在的字段时触发error
: 任何错误发生时都会触发的通用错误事件
模型配置选项:
debounceReactions?: number
: 反应触发的防抖时间(毫秒)asyncValidationTimeout?: number
: 异步验证的超时时间(毫秒)errorFormatter?: (error: ValidationError) => string
: 自定义错误格式化函数
错误处理器提供统一的错误管理:
onError(type: ErrorType, callback: (error: AppError) => void): void
: 订阅特定类型的错误offError(type: ErrorType, callback?: (error: AppError) => void): void
: 取消订阅特定类型的错误triggerError(error: AppError): void
: 触发错误createValidationError(field: string, message: string): AppError
: 创建验证错误createFieldNotFoundError(field: string): AppError
: 创建字段不存在错误- ... 其他错误创建方法
VALIDATION
: 验证错误FIELD_NOT_FOUND
: 字段不存在错误REACTION_ERROR
: 反应处理错误ASYNC_VALIDATION_TIMEOUT
: 异步验证超时错误UNKNOWN
: 未知错误
详细类型定义请参考 src/types.ts
文件。
您可以创建自定义验证规则并设置自定义错误消息:
import { ModelManager, Model } from 'model-reaction';
import { Rule } from 'model-reaction/validators';
// 创建自定义验证规则
const customRule = new Rule(
'custom',
'不符合自定义规则', // 默认错误消息
(value: any) => {
// 自定义验证逻辑
return value === 'custom';
}
);
// 在模型中使用,并重写错误消息
const model = new ModelManager({
field: {
type: 'string',
validator: [
customRule.withMessage('字段值必须为"custom"')
],
default: ''
}
});
import { ModelManager, Model, ValidationRules } from 'model-reaction';
import { ErrorHandler, ErrorType } from 'model-reaction/error-handler';
// 创建错误处理器
const errorHandler = new ErrorHandler();
// 订阅所有验证错误
errorHandler.onError(ErrorType.VALIDATION, (error) => {
console.error(`验证错误: ${error.field} - ${error.message}`);
});
// 订阅字段不存在错误
errorHandler.onError(ErrorType.FIELD_NOT_FOUND, (error) => {
console.error(`字段不存在: ${error.field}`);
});
// 订阅所有错误
errorHandler.onError(ErrorType.UNKNOWN, (error) => {
console.error(`未知错误: ${error.message}`);
});
// 定义模型架构,传入自定义错误处理器
const model = new ModelManager({
name: {
type: 'string',
validator: [ValidationRules.required.withMessage('姓名不能为空')],
default: ''
}
}, {
errorHandler: errorHandler
});
import { ModelManager, Model } from 'model-reaction';
import { Rule } from 'model-reaction/validators';
const asyncModel = new ModelManager({
field: {
type: 'string',
transform: async (value: string) => {
// 异步转换值
return value.toUpperCase();
},
validator: [
new Rule(
'asyncValidator',
'异步验证失败',
async (value: string) => {
// 异步验证逻辑
return value.length > 3;
}
).withMessage('字段长度必须大于3个字符')
],
default: ''
}
});
更多示例请查看 examples/
目录下的文件。
请参考 BEST_PRACTICES.md
文件中的最佳实践指南。