Как можно использовать базовый класс и миксины с компонентом vue-class-component?
Как я могу использовать как базовый класс, так и миксин с vue-class-component?
Связывание функций из миксина непосредственно в шаблоне работает просто отлично, но попытка использовать эти функции в коде машинописного текста приведет к ошибке при компиляции.
Из того, что я понимаю, чтобы использовать миксины, вы должны исходить из них:
class MyComp extends mixins(MixinA, MixinB)
К сожалению, у меня уже есть базовый класс, так что это не вариант. Вот код, который у меня есть... Есть ли способ сделать это с помощью vue-class-component?
// mixin
@Component
export default class DownloadService extends Vue {
public downloadModel(id: string) {
alert('Downloading.');
}
}
// Base class
@Component({
props: {
id: String
}
})
export default class BaseCard extends Vue {
id: string;
protected delete() {
alert('Deleted');
}
}
// Child class
@Component({
props: {
id: String,
disabled: Boolean,
},
mixins: [DownloadService],
})
export default class ItemCard extends BaseCard {
protected clicked() {
// Causes error = S2339: Property 'downloadModel' does not exist on type 'ItemCard'.
this.downloadModel(this.id);
}
}
Обратите внимание, что я могу привести "this" к необходимости, что сработает, но это кажется проблематичным, если мне придется делать это повсеместно:
protected clicked() {
// Ideally shouldn't have to do this casting everywhere.
(<DownloadService><any>this).downloadModel(this.id);
}
1 ответ
Вы действительно не можете расширить несколько классов. Однако TypeScript также поддерживает миксины.
Сначала вам нужно реализовать класс mixin:
// Child class
@Component({
props: {
id: String,
disabled: Boolean,
},
mixins: [DownloadService],
})
export default class ItemCard extends BaseCard implements DownloadService {
protected clicked() {
this.downloadModel(this.id);
}
// DownloadService declaration
public downloadModel: (id: string) => void;
}
А затем вызовите функцию, которая применяет миксин к вашему классу:
applyMixins(ItemCard, [DownloadService]);
Функция applyMixins
это функция, которую вы должны включить где-нибудь во время выполнения:
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
});
});
}
См. Документацию TypeScript по миксинам для получения дополнительной информации: https://www.typescriptlang.org/docs/handbook/mixins.html
Другой вариант - использовать шаблон класса миксина ECMAScript 2015, который также поддерживается начиная с TypeScript 2.2.
Сначала вы должны определить тип где-то для сигнатуры конструкции для определенного типа:
type Constructor<T> = new(...args: any[]) => T;
Затем создайте функцию, которая возвращает новый класс с вашей функцией mixin:
function Downloadable<T extends Constructor<{}>>(Base: T) {
return class extends Base {
public downloadModel(id: string) {
alert('Downloading.');
}
}
}
Тогда вам все еще нужен класс с @Component
декоратор, чтобы определить миксин для Vue:
// mixin
@Component
export class DownloadService extends Downloadable(Vue) {
}
Наконец, вы можете определить класс, в котором вы применяете миксин к базовому классу:
// Child class
@Component({
props: {
id: String,
disabled: Boolean,
},
mixins: [DownloadService],
})
export default class ItemCard extends Downloadable(BaseCard) {
protected clicked() {
this.downloadModel(this.id);
}
}