Skip to content

tjk/vue-o2c

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Jun 20, 2023
cd83908 · Jun 20, 2023
Jun 20, 2023
Oct 24, 2022
Jun 20, 2023
Jun 20, 2023
Oct 23, 2022
Jun 20, 2023
Oct 22, 2022
May 15, 2023
Jun 20, 2023
May 15, 2023
May 10, 2023
May 15, 2023

Repository files navigation

vue-o2c - Vue Options API to Composition API

Demo / Online Playground

WORK IN PROGRESS -- the following is not done:

  • bunch of stuff still not implemented (working through case by case)
  • publish package correctly for CLI command to work (need to check)
  • data() preamble -- if there is preamble maybe just create refs then use the function to set them
  • handle setup() in options api
  • allow options to configure (eg. no typescript)
  • $el needs to try to rewrite part of template
  • would like to maintain indentation

After running, check for FIXME comments

Composition API does not allow easy access of app.config.globalProperties like options API does. vue-o2c takes care of some basic cases (eg. this.$router assuming vue-router) but for others, you will see comments like the following and you must adjust the code depending on how you provide these systems.

const $primevue = inject("primevue") /* FIXME vue-o2c */

Usage

via CLI

This is not working due to a publishing issue I need to fix...

$ npx vue-o2c /path/to/sfc.vue
...
<transformed sfc code>
...

Programmatically

$ pnpm add -D vue-o2c

Please keep in mind, API is very experimental and likely will change!

import { transformPath, transform, type State } from "vue-o2c"

const s1: State = transformPath("/path/to/sfc.vue")
const s2: State = transform("<script>\nexport default {\n  props: {\n    a: String,\n  }\n}\n</script>")
// s1.transformed and s2.transformed will both contained transformed code

Example

Given the following file:

<template lang="pug">
div
  p Wonderful
</template>

<script>
export default {
  props: {
    greeting: {
      type: String,
      default: "Hello",
    },
  },
  data() {
    // this.initializing = true -- would make data() "complex" (need to improve)
    return {
      name: this.$route.query.name || 'John',
      watchMethod: 0,
      watchObject: {
        key: 1,
      },
    }
  },
  methods: {
    meth() {
      console.log(`${this.greeting} ${this.name} ${this.$el.clientHeight}`)
    },
    keyValue: async (a) => {
      await a
    },
  },
  mounted() {
    this.meth()
    this.keyValue()
    delete this.initializing // should not become `delete initializing` (so use $this)
  },
  watch: {
    ["watchMethod"](v) {
      console.log("watchMethod", v)
    },
    "watchObject.key": {
      deep: true,
      immediate: true,
      async handler(v, ov) {
        console.log("watchObject", v, ov)
      },
    },
  },
}
</script>

<style scoped>
:root {
  background: red;
}
</style>
$ git clone [email protected]:tjk/vue-o2c.git
$ cd vue-o2c
$ pnpm i
$ pnpm exec tsx index.ts ./example.vue

Will output the following:

<template lang="pug">
div(ref="$el")
  p Wonderful
</template>

<script setup lang="ts">
import { onMounted, ref, watch } from "vue"
import { useRoute } from "vue-router"

const props = withDefaults(defineProps<{
  greeting?: string
}>(), {
  greeting: "Hello",
})

const $route = useRoute()
const $this = {}

const $el = ref<HTMLElement | undefined>()
const name = ref($route.query.name || 'John')
const watchMethod = ref(0)
const watchObject = ref({
  key: 1,
})

onMounted(() => {
  meth()
  keyValue()
  delete $this.initializing // should not become `delete initializing` (so use $this)
})

watch(() => watchMethod.value, (v) => {
  console.log("watchMethod", v)
})
watch(() => watchObject.value.key, async (v, ov) => {
  console.log("watchObject", v, ov)
}, {
  deep: true,
  immediate: true,
})

function meth() {
  console.log(`${props.greeting} ${name.value} ${$el.value.clientHeight}`)
}
async function keyValue(a) {
  await a
}
</script>

<style scoped>
:root {
  background: red;
}
</style>