装饰器语法
基本概念
DataFaker为了更好的支持ts,引入了装饰器语法,装饰器语法本质上就是defineModel的语法糖,它设计的初衷就是为了保持现有类和模型的共通性。
基本使用
比如现在项目中本来就有User和Address两个类作为 ts 类型
ts
class Address {
declare city: string;
declare children: Address[];
}
// 用户类
class User {
declare id: string;
declare firstName: string;
declare secondName: string;
declare age: number;
declare email: string;
declare address: Address;
declare children: User[];
}为了将这两个类利用起来,而不是重新使用defineModel来定义数据模型,我们可以使用装饰器语法来将现有的类型类定义为User和Address数据模型。
- 使用
@DataModel装饰器定义数据模型,它接受一个模型别名作为参数 - 使用
@DataField装饰器来定义字段,与模板语法中定义字段是一致的
如下所示:
ts
@DataModel('address')
class Address {
@DataField('location.city')
declare city: string;
@DataField({ refModel: 'address', count: 1, deep: 1 })
declare children: Address[];
}
@DataModel('user')
class User {
@DataField('string.uuid')
declare id: string;
@DataField('person.firstName')
declare firstName: string;
@DataField('person.lastName')
declare secondName: string;
@DataField(['number.int', { min: 18, max: 65 }])
declare age: number;
@DataField(ctx => {
return faker.internet.email({ firstName: ctx.firstName, lastName: ctx.secondName });
})
declare email: string;
@DataField({ refModel: 'address', count: 1 })
declare address: Address;
@DataField({ refModel: 'user', deep: 1, count: 1 })
declare children: User[];
}
const userDatas = fakeData('user', 2);
console.dir(userDatas, { depth: Infinity });ts
[
{
id: 'b8e8ade6-5f37-43d9-b512-4ba0395e5975',
firstName: 'Cecile',
secondName: 'MacGyver',
age: 24,
address: { city: 'Leviland', children: { city: 'North Georgianna' } },
children: {
id: 'f29ea63b-ac69-4832-9586-b82b17f2d40b',
firstName: 'Floyd',
secondName: 'Flatley',
age: 57,
address: { city: 'Lake Anissa', children: { city: 'North Beverlyshire' } },
email: 'Floyd.Flatley@hotmail.com',
},
email: 'Cecile_MacGyver34@yahoo.com',
},
{
id: '3647b033-470d-40f3-adf9-836df66f7eef',
firstName: 'Evangeline',
secondName: 'Kerluke',
age: 23,
address: { city: 'Raynorland', children: { city: 'West Rosetta' } },
children: {
id: '350c4642-761f-4b36-a6cf-5b1bcf35edcb',
firstName: 'Aurelio',
secondName: 'Kuvalis',
age: 64,
address: { city: 'Florence-Graham', children: { city: 'New Brock' } },
email: 'Aurelio_Kuvalis61@yahoo.com',
},
email: 'Evangeline.Kerluke@yahoo.com',
},
];装饰器的本质
装饰器的本质就是defineModel的语法糖,它只是对类的定义进行了封装,并没有改变原有的类的结构和行为。
基于类继承的模型继承
DataFaker的强大远不止如此,在前面介绍过,如果要实现模型复用,我们可以克隆一个模型,然后再添加和删除其中的字段。比如像下面一样:
ts
const userModel = defineModel('user', {});
cloneModel('cloneUser', userModel).withProperty('age', { type: 'number.int', min: 18, max: 65 });现在装饰器语法可以更加方便的实现模型继承,只需要像原生继承那样,无需做任何改动,如下所示,User 类从 Person 类的数据模型中继承了 email 和 children 字段:
ts
@DataModel('person')
class Person {
@DataField(ctx => {
return faker.internet.email({ firstName: ctx.firstName, lastName: ctx.secondName });
})
declare email: string;
@DataField({ refModel: 'user', deep: 1, count: 1 })
declare children: User[];
}
@DataModel('user')
class User extends Person {
@DataField('string.uuid')
declare id: string;
@DataField('person.firstName')
declare firstName: string;
@DataField('person.lastName')
declare secondName: string;
@DataField(['number.int', { min: 18, max: 65 }])
declare age: number;
}
const userDatas = fakeData('user', 2);
console.dir(userDatas, { depth: Infinity });ts
[
{
children: {
id: '01beb5dd-d2f8-4602-a4f6-4304d49b1532',
firstName: 'Anjali',
secondName: 'Murphy',
age: 51,
email: 'Anjali.Murphy@hotmail.com',
},
id: '041980c6-164a-4fad-81a2-65a3f9c64359',
firstName: 'Kristy',
secondName: 'Ledner',
age: 62,
email: 'Kristy_Ledner30@yahoo.com',
},
{
children: {
id: '2df47ecb-186e-4d9b-a417-4b62dd4906d0',
firstName: 'Jody',
secondName: 'Schmeler',
age: 18,
email: 'Jody_Schmeler@hotmail.com',
},
id: '26450cf7-f190-44dc-ab1b-6ff0faf8e74b',
firstName: 'Nathanial',
secondName: 'Schaden',
age: 19,
email: 'Nathanial.Schaden96@gmail.com',
},
];操作模型
有时候或许你会更想要操作数据模型,而不是基于类的模型继承,DataFaker 提供了useModel方法来获取原生模型,如下所示:
ts
@DataModel('person')
class Person {
@DataField(ctx => {
return faker.internet.email({ firstName: ctx.firstName, lastName: ctx.secondName });
})
declare email: string;
@DataField({ refModel: 'person', deep: 1, count: 1 })
declare children: User[];
}
@DataModel('user')
class User {
@DataField('string.uuid')
declare id: string;
@DataField('person.firstName')
declare firstName: string;
@DataField('person.lastName')
declare secondName: string;
@DataField(['number.int', { min: 18, max: 65 }])
declare age: number;
}
// 获取user模型和person模型
const userModel = useModel(User);
const personModel = useModel('person');
// 给user模型添加sex字段
userModel?.withProperties({
sex: 'person.sex',
});
const userDatas = fakeData(userModel, 2);
const personDatas = fakeData(personModel, 2);
// 生成数据
console.dir(userDatas, { depth: Infinity });
console.dir(personDatas, { depth: Infinity });结果如下:
基于原型的继承
或许你会想,直接操作userModel会不会导致personModel也发生变化,这里DataFaker已经为你考虑到了,数据模型的继承底层采用了基于原型的继承,基于属性屏蔽,你在userModel上添加的属性不会影响到personModel。所以你无需担心
ts
// userDatas
[
{
id: 'de3a6b97-a5e4-4486-9a24-4a37d4e73f40',
firstName: 'Roel',
secondName: 'Marks',
age: 49,
sex: 'female',
},
{
id: '007224af-3495-4a3b-9eba-6456fca749d5',
firstName: 'Yvette',
secondName: 'Walker',
age: 47,
sex: 'male',
},
][
// personDatas
({
children: { email: 'Zachery12@gmail.com' },
email: 'Alessandra.Kohler@hotmail.com',
},
{
children: { email: 'Eladio_Doyle@yahoo.com' },
email: 'Shanny.Towne@yahoo.com',
})
];