base class 和 mixins 如何与 vue-class-component 一起使用?
How can both a base class and mixins be used with vue-class-component?
如何在 vue-class-component 中同时使用基础 class 和 mixin?
直接在模板中从 mixin 绑定函数工作得很好,但试图在 typescript 代码中使用这些函数会导致编译时出错。
根据我的理解,要使用 mixins,您必须从它们扩展:
class MyComp extends mixins(MixinA, MixinB)
不幸的是,我已经有了一个基础 class,所以这不是一个选择。这是我的代码...有没有办法用 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);
}
您确实不能扩展多个 classes。但是,TypeScript 也支持 mixin。
首先你必须实现mixin class:
// 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;
}
然后调用一个函数,将 mixin 应用到您的 class:
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];
});
});
}
有关 mixin 的详细信息,请参阅 TypeScript 文档:https://www.typescriptlang.org/docs/handbook/mixins.html
另一个选择 是使用 ECMAScript 2015 mixin class 模式,自 TypeScript 2.2 起也支持该模式。
您首先必须在某处为特定类型的构造签名定义类型:
type Constructor<T> = new(...args: any[]) => T;
然后创建一个函数,该函数 returns 一个新的 class 具有您的混合功能:
function Downloadable<T extends Constructor<{}>>(Base: T) {
return class extends Base {
public downloadModel(id: string) {
alert('Downloading.');
}
}
}
那么你仍然需要一个 class 和 @Component
装饰器来定义 Vue 的混合:
// mixin
@Component
export class DownloadService extends Downloadable(Vue) {
}
最后,您可以定义 class 将 mixin 应用于基础 class:
// Child class
@Component({
props: {
id: String,
disabled: Boolean,
},
mixins: [DownloadService],
})
export default class ItemCard extends Downloadable(BaseCard) {
protected clicked() {
this.downloadModel(this.id);
}
}
如何在 vue-class-component 中同时使用基础 class 和 mixin?
直接在模板中从 mixin 绑定函数工作得很好,但试图在 typescript 代码中使用这些函数会导致编译时出错。
根据我的理解,要使用 mixins,您必须从它们扩展:
class MyComp extends mixins(MixinA, MixinB)
不幸的是,我已经有了一个基础 class,所以这不是一个选择。这是我的代码...有没有办法用 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);
}
您确实不能扩展多个 classes。但是,TypeScript 也支持 mixin。
首先你必须实现mixin class:
// 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;
}
然后调用一个函数,将 mixin 应用到您的 class:
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];
});
});
}
有关 mixin 的详细信息,请参阅 TypeScript 文档:https://www.typescriptlang.org/docs/handbook/mixins.html
另一个选择 是使用 ECMAScript 2015 mixin class 模式,自 TypeScript 2.2 起也支持该模式。
您首先必须在某处为特定类型的构造签名定义类型:
type Constructor<T> = new(...args: any[]) => T;
然后创建一个函数,该函数 returns 一个新的 class 具有您的混合功能:
function Downloadable<T extends Constructor<{}>>(Base: T) {
return class extends Base {
public downloadModel(id: string) {
alert('Downloading.');
}
}
}
那么你仍然需要一个 class 和 @Component
装饰器来定义 Vue 的混合:
// mixin
@Component
export class DownloadService extends Downloadable(Vue) {
}
最后,您可以定义 class 将 mixin 应用于基础 class:
// Child class
@Component({
props: {
id: String,
disabled: Boolean,
},
mixins: [DownloadService],
})
export default class ItemCard extends Downloadable(BaseCard) {
protected clicked() {
this.downloadModel(this.id);
}
}