情景
比如我们可能在项目中会这样子写一个computed
selectGroup(): Model.Part[] {
get() {
return this.partSelection.selectGroup;
},
set(newValue: any) {
const option = {
selectGroup: newValue,
}
this.set_partData(option);
}
},
name(): string {
get() {
return this.partSelection.name;
},
set(newValue: any) {
const option = {
age: newValue,
}
this.set_partData(option);
}
},
age(): number {
get() {
return this.partSelection.age;
},
set(newValue: any) {
const option = {
age: newValue,
}
this.set_partData(option);
}
},
color(): string {
get() {
return this.partSelection.color;
},
set(newValue: any) {
const option = {
color: newValue,
}
this.set_partData(option);
}
},
这个时候你会发现其实写了很多相似的computed结构,这时候你想到了vuex的mapState
...mapState({
partSelection: (state: any) => state.screen.editor.partSelection
}),
疑问
我能否也封装一个类似的函数,实现只需要传入一系列的值,自己构建成computed呢?如下:
...mapDataSource(['name', 'age', 'color']),
步骤分解
分解一下mapState的情况,
- 是对象展开符...,将一个对象混入computed中
- 可传入参数,可以是对象,可以是数组,其实就是你需要被进一步封装为computed属性的一系列值。
- 执行mapState函数并返回一个即将被结构的对象
- 被解构的对象中,每个属性应该和computed平时的写法是一样的,也就是如下
age(): number {
return this.partSelection.age;
},
或
age(): number {
get() {
return this.partSelection.age;
},
set(newValue: any) {
const option = {
age: newValue,
}
this.set_partData(option);
}
},
结论
每个属性都是方法的引用常量,且该方法中的上下文(this),都会是vue组件环境
所以根据上面的分析,很容易能够写出如下的封装:
// 类似mapState
const mapDataSource = (dataSourceProp: string[]) => {
const computedProp: any = {};
for (const prop of dataSourceProp) {
computedProp[prop] = {
get() {
return (this.partData && this.partData[prop]) || '';
},
set(newValue: any) {
const option = {
[prop]: newValue,
}
this.set_partData(option);
}
}
}
return computedProp;
};
优化
如果我们还有更复杂的情况,可能我们需要不同的数据源,可能我们需要对set方法中每个属性自定义内容,那么我们可以这么写:
...mapDataSource({
sourceType: {
// 需要从哪个对象上获取自身的属性
carrier: 'partData',
// 设置自身属性的简单适配器
getOption: (newValue: any) => {
return {
sourceType: newValue,
}
},
},
valueType: {
carrier: 'pointData',
getOption: (newValue) => {
return {
valueType: newValue,
mode: 'pointData',
}
},
}
}),
// 类似mapState
const mapDataSource = (dataSourceProp: any) => {
const computedProp: any = {};
for (const [name, prop] of Object.entries(dataSourceProp)) {
computedProp[name] = {
get() {
return (this[prop.carrier] && this[prop.carrier][name]) || '';
},
set(newValue: any) {
const option = prop.getOption(newValue);
this.set_partData(option);
}
}
}
return computedProp;
};
这样就能做到灵活的computed属性封装啦,类似mapState.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。