wonderful-panda/vue-tsx-support

functional api support

Kingwl opened this issue ยท 6 comments

u3u commented

The ofType<Props>().covert method should support ComponentOptions and FunctionalComponentOptions and should even support pure functions that return VNode | VNode[].

import { RenderContext } from 'vue';
import { ofType } from 'vue-tsx-support';

export interface HelloProps {
  msg: string;
}

const Hello = ({ props }: RenderContext<HelloProps>) => (
  <div class="hello">{props.msg}</div>
);

// Now you need to use `as any` or `// @ts-ignore` to ignore type checking.
export default ofType<HelloProps>().convert(Hello as any);
import Vue from 'vue';
import { createComponent, value, onMounted } from 'vue-function-api';
import { ofType } from 'vue-tsx-support';

type Inject = {
  count: number;
};

const Counter = createComponent({
  setup() {
    const count = value(0);

    onMounted(() => {
      window.setTimeout(() => {
        count.value++;
      }, 3000);
    });

    return { count };
  },

  render(this: Vue & Inject) {
    const { count } = this;
    return <div class="counter">{count}</div>;
  },
});

// @ts-ignore
export default ofType().covert(Counter);

I'm still considering how should we support composition-api.
This is workaround for now.

  1. setup @vue/composition-api and babel-preset-vca-jsx according to their READMEs.

  2. Put this code into your project. (for explanation, save as vca.ts)

import Vue, { VNode } from "vue";
import {
  PropsForOutside,
  RequiredPropNames,
  TsxComponent
} from "vue-tsx-support";
import { createComponent } from "@vue/composition-api";
import { RecordPropsDefinition } from "vue/types/options";
import { SetupContext } from "@vue/composition-api";

export interface CompositionComponentOptions<
  Props,
  PropsDef extends RecordPropsDefinition<Props>
> {
  name?: string;
  props?: PropsDef;
  setup(this: void, props: Props, ctx: SetupContext): () => VNode;
}

export interface ComponentFactory<EventsOn> {
  create<
    Props,
    PropsDef extends RecordPropsDefinition<Props>,
    RequiredProps extends keyof Props = RequiredPropNames<PropsDef> &
      keyof Props
  >(
    options: CompositionComponentOptions<
      Props,
      PropsDef & RecordPropsDefinition<Props>
    >
  ): TsxComponent<Vue & Props, PropsForOutside<Props, RequiredProps>, EventsOn>;
}

const factory = {
  create(options: any): any {
    return createComponent(options);
  }
} as ComponentFactory<{}>;

export const component = factory.create;

export function componentFactoryOf<EventsOn>(): ComponentFactory<EventsOn> {
  return factory;
}

And you can use composition-api with TSX like below

import { ref, onMounted } from "@vue/composition-api";
import * as vca from "./vca";

export const Counter = vca.component({
  props: {
    initialValue: { type: Number, default: 0 }
  },
  setup(props) {
    const count = ref(props.initialValue);
    onMounted(() => {
      window.setTimeout(() => {
        count.value++;
      }, 3000);
    });
    return () => <div>{count.value}</div>;
  }
});
dvic commented

@wonderful-panda maybe it's better to implement the support for TSX types directly in @vue/composition-api? I can imagine a lot of people would be happy about this :)

@wonderful-panda Two things I wanted to ask:

  1. Maybe we should rename this issue to composition-api ๐Ÿ˜‰
  2. I'm confused about the difference between vue-tsx-support and babel-preset-vca-jsx, are they both Vue compilers to convert TSX files into regular Vue files? Is there anywhere I can read more information about that?

I've released 3.0.0-beta.7 which works with @vue/composition-api and babel-preset-vca-jsx.

@wonderful-panda I'm thinking of upgrading to v3 to be able to use the composition api.

I see it's still under heavy development though. When you think you think is a good time to upgrade? I want to avoid my project from crashing when I upgrade all package minor updates. : D