Skip to content

Instantly share code, notes, and snippets.

@bendytree
Created October 23, 2024 14:50
Show Gist options
  • Save bendytree/ad6c29058b7717919e58d0d3672f7656 to your computer and use it in GitHub Desktop.
Save bendytree/ad6c29058b7717919e58d0d3672f7656 to your computer and use it in GitHub Desktop.

Instructions

The following file was just migrated from Vue 2 to Vue 3, but there is one task remaining. Vue 3 does not allow exports within a "setup" script. So you must create a new typescript script tag (above the setup script). We will call this new script tag the "standard" script and it will contain all imports, exports, etc.

Please respond with the updated code. Do not include comments like "Here is the code". Your response will be saved in place of the old file (so DO NOT include comments or markdown formatting).

If you have concerns during your conversion then include a comment like this:

// TODO: (reason for concern)

DO NOT remove any comments such as TODO statements!

Strategy

Start by moving ALL the setup code into the standard script. Imports and exports should always be in the "standard" script.

IF code falls into one of these categories, then it may be moved down into the "setup" script:

  • Code that is specific to an instance of a component
  • onMounted(...), watch(...), computed(...), etc
  • DOM event handlers
  • refs, classes, functions, or other variables that are not exported
  • use statements such as useManager, useModal, etc (useWindow is an exception, it should stay in the standard tag)

To be clear! All exports must be exported within the standard script.

Here is an example:

<script lang="ts" setup>
import { watch } from 'vue';
import { Bar } from 'src/bar/types.ts';
import { Counter } from 'src/counter.ts';

export interface IFoo { bar:Bar; } // bad
export const foo = 'bar'; // bad
export class Fizz { // bad
  constructor(args){
    watch(() => args.x, () => console.log());
  }
}

const count = new Counter(0);

watch(() => count, () => console.log('changed!'));

export const doSomething = () => {};

const onClick = () => { doSomething(); };
</script>
<script lang="ts">
import { watch } from 'vue';
import { Bar } from 'src/bar/types.ts';
import { Counter } from 'src/counter.ts';
export interface IFoo { bar:Bar; }
export const foo = 'bar';
export class Fizz {
  constructor(args){
    watch(() => args.x, () => console.log());
  }
}
export const doSomething = () => {};
</script>

<script lang="ts" setup>
import { watch } from 'vue';

const count = new Counter(0);
watch(() => count, () => console.log('changed!'));

const onClick = () => { doSomething(); };
</script>

Here is another way to think of it. The standard script code runs when the page loads. The setup script runs when the component is instantiated.

Self Referencing

Occasionally an SFC references itself:

<script>
const Modal = defineComponent({ ... });
launchModal({ component: Modal });
</script>

Now this is possible by importing

<script>
import Modal from './my-modal.vue';
launchModal({ component: Modal });
</script>
<script setup>

</script>

FINAL THOUGHTS

  • Keep the <template> tag before any script tags.
  • Do not include empty script tags. Just omit the tag all together.

DO NOT FORGET ANY EXPORTS!!!

  • If any interface, class, variable, etc was exported originally, then IT MUST BE EXPORTED in the updated code.
  • If it was not exported originally, then do not export it now
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment