【问题标题】:How can both a base class and mixins be used with vue-class-component?基类和 mixins 如何与 vue-class-component 一起使用?
【发布时间】:2019-01-18 08:59:15
【问题描述】:

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

直接在模板中绑定来自 mixin 的函数可以正常工作,但尝试在 typescript 代码中使用这些函数会导致编译时出错。

据我了解,要使用 mixins,您必须从它们扩展:

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

【问题讨论】:

  • 我没有尝试过扩展基类,但为了彻底解决 mixins 问题,我结束了创建这个:github.com/justrhysism/vue-mixin-decorator -- 没有作为答案提交,我'我不确定它实际上是一个。

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


【解决方案1】:

你确实不能扩展多个类。但是,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);
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 2018-04-16
    • 2018-04-06
    • 2019-10-20
    • 2021-10-27
    • 1970-01-01
    • 2019-08-04
    • 2020-02-25
    相关资源
    最近更新 更多