vue-class-component如何同时使用基类和mixins?

时间:2018-08-10 17:48:39

标签: typescript vue.js vue-class-components

如何在vue-class-component中同时使用基类和mixin?

直接从模板中的mixin绑定函数很好,但是尝试在打字稿代码中使用这些函数会在编译时导致错误。

根据我的理解,使用mixin必须从它们扩展:

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 个答案:

答案 0 :(得分:2)

您确实不能扩展多个类。但是,TypeScript也支持mixins。

首先,您必须实现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;
}

然后调用将mixin应用到您的类的函数:

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];
        });
    });
}

有关更多信息,请参见关于mixins的TypeScript文档:https://www.typescriptlang.org/docs/handbook/mixins.html


另一个选项是使用ECMAScript 2015 mixin类模式,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:

// mixin
@Component
export class DownloadService extends Downloadable(Vue) {
}

最后,您可以定义将mixin应用于基类的类:

// Child class
@Component({
  props: {
    id: String,
    disabled: Boolean,
  },
  mixins: [DownloadService],
})
export default class ItemCard extends Downloadable(BaseCard) {
  protected clicked() {
    this.downloadModel(this.id);
  }
}