vue-codemod icon indicating copy to clipboard operation
vue-codemod copied to clipboard

Vue2 class-based Options API to Vue2 native Options API transformation [proposal PR]

Open matrunchyk opened this issue 3 years ago • 3 comments

Hello!

I prepared a transformation that converts class-based Options API to Vue2 native Options API with TypeScript support

So this example code:

<script lang="ts">
import Component from 'vue-class-component';
import Vue from 'vue';
import { Prop, Watch } from 'vue-property-decorator';
import TestComponent1 from './TestComponent1/TestComponent1.vue';
import TestComponent2 from './TestComponent2/TestComponent2.vue';
import { ExampleType } from './ExampleType';

@Component({
  components: {
    TestComponent1,
    TestComponent2,
  },
})
export default class TestComponent extends Vue {
  @Prop({ default: () => true }) example!: ExampleType[];

  @Prop() prop1!: string;

  @Prop({ default: 0 }) prop2!: number;

  @Watch('prop1', { deep: true, immediate: true})
  onProp1Changed() {
    console.log('Example watcher')
  }

  data1 = true;

  get computed1(): boolean {
    return !!this.prop2;
  }

  method1() {
    console.log('Example method')
  }

  created() {
    console.log('created hook')
  }
}
</script>

can be converted with this transformation to this one:

<script lang="ts">
import TestComponent1 from './TestComponent1/TestComponent1.vue';
import TestComponent2 from './TestComponent2/TestComponent2.vue';
import { ExampleType } from './ExampleType';
import { Vue, defineComponent } from "vue";

export default defineComponent({
  components: {
    TestComponent1,
    TestComponent2,
  },

  name: "TestComponent",

  props: {
    example: {
      type: Object as PropType<ExampleType[]>,
      required: true,
      default: () => true
    },

    prop1: {
      type: String as PropType<string>,
      required: true
    },

    prop2: {
      type: Number as PropType<number>,
      required: true,
      default: () => 0
    }
  },

  data: () => ({
    data1: true
  }),

  computed: {
    computed1() {
      return !!this.prop2;
    }
  },

  watch: {
    prop1: {
      deep: true,
      immediate: true,

      handler() {
        console.log('Example watcher')
      }
    }
  },

  created() {
    console.log('created hook')
  },

  methods: {
    method1() {
      console.log('Example method')
    }
  }
});
</script>

cc @sodatea

matrunchyk avatar Nov 24 '21 13:11 matrunchyk

If you think this can be useful to the community, let me know, so I'll add relevant tests. If not, no problem, I'll continue using my fork for my needs and merge it there.

This basically might be useful for ones who want to migrate from class-based components (vue-property-decorator, vue-class-component) to Vue2 Options API and then to Vue3 eventually.

Thanks :)

matrunchyk avatar Nov 24 '21 13:11 matrunchyk

It would be very useful! Since we started our code base in 2017, vue-class-component was the way to do to have typescript support. Now, many years after, we have hundreds of component built with vue-class-component and since Vue 2 will be EOL in december 2023, we have to move away from that API to migrate to Vue 3.

vidal7 avatar Nov 03 '22 18:11 vidal7

Hi @matrunchyk @sodatea any update on when can we merge this. This is very helpful for those who are using class based code with TS and want to migrate to vue3

Satakshi-ctrl avatar Mar 06 '24 05:03 Satakshi-ctrl