facing-dev / vue-facing-decorator

Vue typescript class component decorators
MIT License
356 stars 32 forks source link

export static functions in compile to component #125

Open rien-vroom-cquential opened 4 months ago

rien-vroom-cquential commented 4 months ago

In the old vue class components we could define a public static function which would be callable from other components/locations. This original functionality is defined here i believe: https://github.com/vuejs/vue-class-component/blob/master/src/component.ts#L119

Anyhow i think public static functions should be added to the exported class/object in https://github.com/facing-dev/vue-facing-decorator/blob/master/src/component.ts#L74 However i'm not capable enough to make a sane solution for this (e.g. im not sure how to handle inheritance and other side effects).

Normally you can use a seperate ts class or something. But we want to use this for a lib and its really helpfull to have these kind of functions included in the component instead of a "random" other ts file/object/class

Minimal reproducable code:

### App.vue
<script lang="ts">
import { Component, Vue } from 'vue-facing-decorator'
import HelloWorld from './components/HelloWorld.vue'

@Component({
    components: {HelloWorld}
})
export default class App extends Vue {
    public get failingMsg(): string {
        return HelloWorld.staticFunctionCall('test');
    }
}
</script>
<template>
  <main>
    <HelloWorld :msg="failingMsg" />
  </main>
</template>

### HelloWorld.vue
<script lang="ts">
import { Component, Vue, Prop } from 'vue-facing-decorator'

@Component
export default class HelloWorld extends Vue {
    @Prop() public msg!: string;

    public static staticFunctionCall(changeA: string): string {
        // Do something
        return changeA;
    }
}
</script>
<template>
    {{ msg }}
</template>

Error received in the browser:

App.vue:9 Uncaught TypeError: HelloWorld.staticFunctionCall is not a function
    at get refMsg (App.vue:9:27)
    at ReactiveEffect.fn (chunk-U6BEPC57.js?v=e33feee7:1236:13)
    at ReactiveEffect.run (chunk-U6BEPC57.js?v=e33feee7:435:19)
    at get value (chunk-U6BEPC57.js?v=e33feee7:1248:107)
    at Object.get [as refMsg] (chunk-U6BEPC57.js?v=e33feee7:4970:22)
    at Object.get (chunk-U6BEPC57.js?v=e33feee7:4530:19)
    at Proxy._sfc_render (App.vue:21:25)
    at renderComponentRoot (chunk-U6BEPC57.js?v=e33feee7:2350:17)
    at ReactiveEffect.componentUpdateFn [as fn] (chunk-U6BEPC57.js?v=e33feee7:7466:46)
    at ReactiveEffect.run (chunk-U6BEPC57.js?v=e33feee7:435:19)

The code above is perfectly valid by (vue-)tsc and eslint, but fails in the browser.

ruojianll commented 3 months ago
### HelloWorld.vue
<script lang="ts">
import { Component, Vue, Prop } from 'vue-facing-decorator'

@Component
export default class HelloWorld extends Vue {
    @Prop() public msg!: string;
}

export function staticFunctionCall(changeA: string): string {
    // Do something
    return changeA;
}
</script>
<template>
    {{ msg }}
</template>

Try export static functions as module values.

rien-vroom-cquential commented 3 months ago

@ruojianll that does work for this case. It is somewhat impractical when building a lib with many components.

For example:

We export all the components in one go (aka all the default exports) so we can use the following:

import {MyComponent1, MyComponent2} from '@mycompany/ui-library';

They would both have a staticFunctionCall that does something slightly different. E.g. sorting data a certain way. Since we are importing from the combined export function from the ui-library we can't really have this functionality.

We are following the example given by vite: https://vitejs.dev/guide/build#library-mode so we export all components from the entrypoint in the lib. So basically we have to use (if we follow the example in the initial post) in the lib:

import {HelloWorld, staticFunctionCall as HelloWorldStaticFunctionCall } from './HelloWorld.vue';

export {HelloWorld, HelloWorldStaticFunctionCall}

And this is the exact example we try to avoid, since the function itself is really tied to the HelloWorld class, why should we need to export something extra for this?

This suggestion might fix the TS errors, but is such a shift in the way the ui-library will work, its something we really would like to avoid.

Anyhow I'm still of the opinion that a static function should be exported/accesible from the outside, as that is what TS is also exporting.

SIdenote: thanks for the amazing work you've done here!