typescript 如何使用“tc39”装饰器将类定义转换为Vue 3组件定义?

9nvpjoqh  于 2023-04-13  发布在  TypeScript
关注(0)|答案(1)|浏览(92)

bounty已结束。回答此问题可获得+50声望奖励。奖励宽限期将在9小时后结束。Takeshi Tokugawa YD正在寻找规范答案

tc 39/proposal-decorators中的API与以前的decorators API有很大的不同。虽然TypeScript 5 does not fully support the new API yet,但以前的API的弃用是迟早的事,所以我将使用最新的API进行开发。
问题Into what we need to convert the TypeScript class using decorators to get the valid Vue component?的答案对于旧的API是实际的,但是现在需要用最新的API来解决同样的问题。
初始代码为

import { defineComponent } from "vue";

/* [ Theory ] Overrides the eponymous type of "typescript/lib/lib.decorators.d.ts".
*  [ Reference ] https://github.com/tc39/proposal-decorators#classes */
type ClassDecorator = (value: Function, context: {
  kind: "class";
  name: string | undefined;
  addInitializer: (initializer: () => void) => void;
}) => Function | void;

const VueComponentOptions: ClassDecorator = (targetClass: Function, context: ClassDecoratorContext): Function | void => {

  // TODO check for the kind === "class"

  const vueOptions: ComponentOptions = {
    methods: {},
    computed: {}
  };

  return defineComponent(vueOptions);

};

目前,使用

/* https://stackoverflow.com/questions/75909821/the-classdecorator-type-defined-in-tc39-proposal-decorators-is-not-applicabl */
/* @ts-ignore TS1270 TS decorators are not fully TC39-compatible yet. */
@VueComponentOptions
export default class ReactiveStateExperimentalSample {

}

导致错误

ReactiveState-ExperimentalSample.vue?../../node_modules/ts-loader/index.js??clonedRuleSet-1!../../node_modules/vue-loader/dist/index.js??ruleSet%5B1%5D.rules%5B10%5D.use%5B0%5D:7
Uncaught TypeError: Function expected
    ... ```

起因是
如果返回除函数之外的任何其他类型的值,则将抛出错误。
https://github.com/tc39/proposal-decorators#classes
也许我需要 Package defineComponent才能正常工作?

const VueComponentOptions: ClassDecorator = (targetClass: Function, context: ClassDecoratorContext): Function | void => {

  const vueOptions: ComponentOptions = {
    methods: {},
    computed: {}
  };

  return (): ReturnType<typeof defineComponent> => defineComponent(vueOptions);

};

这一次,没有JavaScript运行时错误,但Vue会发出警告:
runtime-core.esm-bundler.js:170 [Vue warn]:无效的VNode类型:undefined(未定义)at
并且当然将不呈现该组件。
对于最新的装饰器API + Vue 3用例,我需要在VueComponentOptions中做什么?
请不要推荐第三方库,因为这个问题的重点是实现。

m2xkgtsf

m2xkgtsf1#

  • 您正在尝试:
  • 重新实现一个更新的vue-class-component替代方案:一个返回ReturnType<typeof defineComponent>的类,带有tc 39装饰器

如果我理解错了,请纠正我。

<script lang="ts">
import { defineComponent, ComponentPublicInstance } from 'vue';

import type { ComponentPublicInstance } from 'vue';
// you need a class saying it implements ComponentPublicInstance for this.$props and other acessors
const ComponentPublicInstanceClass =
  class {} as any as new (...a: any[]) => ComponentPublicInstance;

@(function VueComponentOptions(cls) { // inplace to see implecit typings
  return defineComponent({
    name: cls.name,
    data: () => new cls(), // maybe like this or whatever way you want
    props: ['msg'],
    // whatever else you need
  }) as any; // you won't be able to extens this class anymore but that's ok
})
export default class MyComponent implements ComponentPublicInstanceClass {
  text = 'from class';
  fn() {
    this.$props; // has acess to all things in ComponentPublicInstance 
  }
}
</script>

<template>
  <h1>{{ msg }} {{ text }}</h1>
</template>

有关更多信息,请参阅alike thing的实现,网址:https://github.com/facing-dev/vue-facing-decorator/blob/master/src/index.ts#L29
如果希望同时使用@Ops class@Ops({...etc}) class,则需要(data: object) => ClassDecorator重载

相关问题