在一个列表中选择、并对选择项进行操作的场景并不少见,所以可以封装一个如下所示的类,来抽离其中的公用逻辑:
import {ObjectFunctionBinder} from "../ObjectFunctionBinder";
import {Confirm} from "../ElHints";
// 使用一个永远不可能被作为标识符(id)的值作为以下常量的值
const NewUnitIdentifier = -91
export abstract class CommonOperation<UnitType> {
selectedUnit: UnitType = null as unknown as UnitType;
selectedIndex: number = -1; // -1: select none; NewUnitIdentifier: a new unit; else: an existing unit
typeName: new () => UnitType;
// 传入一个构造函数
// like "class A{ constructor(){} };"
// then "CommonOperation(A)";
// 不过抽象类不能直接实例化哦BTW
protected constructor(typeName: new () => UnitType) {
this.typeName = typeName;
// 由于外部调用时,this不一定指向创建出来的对象
// 这个函数的作用是将本类的所有函数的this永久指向自己(对象)
// like "this.handleUnit = this.handleUnit.bind(this);"
ObjectFunctionBinder(this);
this.cancelSelection();
}
handleUnit(mode: 'add' | 'delete' | 'modify' | 'select', target: UnitType, index: number) {
switch (mode) {
case 'add':
if (this.selectedIndex === NewUnitIdentifier) return;
this.selectedIndex = NewUnitIdentifier;
this.selectedUnit = new this.typeName();
break;
case 'delete':
// 二次确认
// 读者可将这里理解为ElMessageBox.comfirm
Confirm('确定删除吗?', '警告').then(() => {
this.conductDelete(target, index).then(() => {
if (this.selectedIndex === index) {
this.cancelSelection();
}
});
})
break;
case'modify':
// 对于持久化的,以及未持久化的,做不同的操作
if (this.isNewUnit()) {
this.conductAdd(target, index)
} else {
this.conductModify(target, index)
}
break;
case'select':
this.selectedIndex = index;
this.selectedUnit = target;
break;
}
}
cancelSelection() {
this.selectedUnit = new this.typeName();
this.selectedIndex = -1;
}
isNewUnit() {
return this.selectedIndex === NewUnitIdentifier;
}
// 用于继承,随后改写
abstract conductAdd(target: UnitType, index: number): void;
abstract conductDelete(target: UnitType, index: number): Promise<any>;
abstract conductModify(target: UnitType, index: number): void;
}