Skip to content

Use class style to write setup and support vue2 and vue3

License

Notifications You must be signed in to change notification settings

dp-os/vue-class-setup

Repository files navigation

vue-class-setup

Build Status Coverage Status npm npm npm

Why?

Using class can help you avoid ref, reactive and computed, and significantly reduce your mental burden and better organize your code. It supports vue2 and vue3 at the same time. After gzip compression, it is only 1KB

Install

npm install vue-class-setup
# or
yarn add vue-class-setup

Quick start

<script lang="ts">
import { onMounted } from 'vue';
import { Setup, PassOnTo } from 'vue-class-setup';

@Setup
class Count {
    public value = 0;
    public get text() {
        return String(this.value);
    }
    public set text(text) {
        this.value = Number(text);
    }
    @PassOnTo(onMounted)
    public init() {
        this.value++;
    }
}
</script>
<script setup lang="ts">
// Use the class you write in setup
const count = new Count();
</script>
<template>
    <p>{{ count.text }}</p>
    <input type="number" v-model="count.text" />
</template>

PassOnTo

This callback will be called back after the Test class instantiation is completed, and the decorated function will be passed in, and the TS can check whether the type is correct

class Test {
    @PassOnTo(myFunc)
    public init(name: string) {}
}

function myFunc (callback: (name: string) => void) {
    // ...
}

If PassOnTo does not pass in a handler, it is called after reactive and computed execution are completed, You should avoid watching in the constructor because it may not have reactive

import { Watch } from 'vue';

@Setup
class Count {
    public value = 0;
    @PassOnTo()
    private setup() {
        // Safe Watch
        watch(
            () => this.value,
            (value) => {
                // ...
            }
        );
    }
}

Define

If the component defines props, writing class in setup will cause the setup function to create a class every time it is executed, which will increase the cost. Therefore, we should avoid writing class in setup and use Define basic class to receive props and Emits. The following example provides a best practice

<script lang="ts">
import { Setup, Define } from 'vue-class-setup'

@Setup
class App extends Define<Props, Emits> {
    public get text() {
        return String(this.props.value);
    }
    public click(evt: MouseEvent) {
        this.emit('click', evt);
    }
}

</script>
<script lang="ts" setup>

export interface Props { value: number }

export interface Emits {
    (event: 'click', evt: MouseEvent): void;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

const app = new App(props, emit);

</script>
<template>
    <button class="btn" @click="app.click($event)">
        <span class="text">{{ app.text }}</span>
    </button>
</template>