{"_rev":"64-aa5be785a0124801fa7e180f5477db05","time":{"created":"2025-11-07T07:01:06.803Z","modified":"2025-11-07T07:01:07.399Z","0.0.1":"2022-07-28T11:53:38.276Z","0.0.2":"2022-08-01T09:04:20.333Z","0.0.3":"2022-08-01T09:48:08.630Z","0.0.4":"2022-08-02T12:43:11.193Z","0.0.5":"2022-08-02T12:45:59.569Z","0.0.6":"2022-08-02T12:48:48.075Z","0.0.7":"2022-08-02T12:50:51.598Z","0.0.8":"2022-08-02T13:18:32.700Z","0.0.9":"2022-08-04T10:56:04.840Z","0.1.0":"2022-08-10T02:20:56.088Z","0.1.1":"2022-08-10T02:27:37.995Z","0.1.2":"2022-08-10T05:26:50.653Z","0.1.3":"2022-08-11T03:40:33.766Z","0.1.4":"2022-08-11T11:35:18.940Z","1.0.0":"2022-08-14T08:19:46.914Z","1.0.1":"2022-08-14T08:27:24.230Z","1.0.2":"2022-08-14T09:48:29.121Z","1.0.3":"2022-08-16T07:53:58.414Z","1.0.4":"2022-08-16T09:10:54.023Z","1.0.5":"2022-08-16T09:24:42.966Z","1.0.6":"2022-08-17T01:47:34.324Z","1.0.7":"2022-08-17T03:42:19.023Z","1.0.8":"2022-08-17T08:51:15.062Z","1.1.0":"2022-08-18T08:53:22.858Z","1.1.1":"2022-08-19T03:48:22.250Z","1.1.2":"2022-08-19T05:31:28.927Z","1.1.3":"2022-08-19T06:46:24.197Z","1.1.5":"2022-08-20T18:07:28.827Z","1.1.6":"2022-08-21T08:21:39.356Z","1.1.7":"2022-08-21T08:29:53.326Z","1.1.8":"2022-08-22T02:56:38.694Z","1.1.9":"2022-08-22T05:43:29.992Z","1.2.0":"2022-08-23T12:49:21.441Z","1.2.1":"2022-08-24T07:52:01.019Z","1.2.2":"2022-08-25T04:00:42.093Z","1.2.3":"2022-08-26T10:30:40.439Z","1.2.4":"2022-08-29T04:15:57.612Z","1.2.5":"2022-09-01T09:23:44.472Z","1.2.6":"2022-09-02T10:24:27.887Z","1.2.7":"2022-09-06T02:07:32.799Z","1.2.8":"2022-09-07T04:53:11.461Z","1.2.9":"2022-09-07T10:08:50.590Z","1.2.8-beta":"2022-09-07T10:30:24.285Z","1.2.8-beta2":"2022-09-07T10:31:18.082Z","1.3.0":"2022-09-07T10:40:58.932Z","1.3.2":"2022-09-14T05:24:46.663Z","1.3.3":"2022-09-14T06:09:42.878Z","1.3.4":"2022-09-27T15:15:33.555Z","1.3.5":"2022-11-20T12:21:51.549Z","1.3.6":"2022-11-20T12:31:32.702Z","1.3.7":"2022-12-23T03:37:12.441Z","1.3.8":"2023-07-19T03:25:54.631Z","1.3.9":"2023-10-20T06:29:25.284Z","1.4.0":"2023-10-23T09:31:16.177Z","1.4.1":"2023-10-26T04:56:39.239Z","1.4.2":"2023-12-24T03:31:25.485Z","1.4.3":"2024-07-19T06:39:42.496Z","1.4.4":"2024-07-19T08:54:49.339Z","1.4.5":"2025-11-07T07:01:07.040Z"},"_id":"vue-class-setup","name":"vue-class-setup","dist-tags":{"latest":"1.4.5"},"versions":{"1.4.5":{"name":"vue-class-setup","version":"1.4.5","main":"dist/index.cjs.js","module":"dist/index.es.js","types":"dist/index.d.ts","repository":{"type":"git","url":"git+ssh://git@github.com/fmfe/vue-class-setup.git"},"author":{"email":"1340641314@qq.com"},"license":"MIT","description":"Use class style to write setup and support vue2 and vue3","exports":{".":{"types":"./dist/index.d.ts","import":{"node":"./dist/index.mjs","default":"./dist/index.es.js"},"require":"./dist/index.cjs.js"},"./package.json":"./package.json"},"sideEffects":false,"keywords":["vue-class","vue-class-component","vue-property-decorator","vue-class-composition","vue-class-composition-api"],"scripts":{"lint":"prettier --write .","dev":"vite","build":"vue-tsc --noEmit && vite build && cp dist/index.es.js ./dist/index.mjs","preview":"vite preview","test":"vitest","test:all":"./script/test-all.sh","coverage":"vitest run --coverage","coveralls":"coveralls < coverage/lcov.info","release":"yarn test:all && ./script/release.sh"},"peerDependencies":{"vue":">=2.7.8 || >=3.0.0"},"devDependencies":{"@vitejs/plugin-vue":"^6.0.1","@vue/test-utils":"^2.4.6","@vitest/coverage-v8":"4.0.7","coveralls":"^3.1.1","happy-dom":"^20.0.10","prettier":"^3.6.2","typescript":"^5.9.3","vite":"^7.2.2","vite-plugin-dts":"^4.5.4","vitest":"^4.0.7","vue":"^3.5.23","vue-tsc":"^3.1.3"},"_id":"vue-class-setup@1.4.5","gitHead":"ba5c91bc270304c71336a54adf261687f293cdbd","bugs":{"url":"https://github.com/fmfe/vue-class-setup/issues"},"homepage":"https://github.com/fmfe/vue-class-setup#readme","_nodeVersion":"24.3.0","_npmVersion":"11.4.2","dist":{"integrity":"sha512-MQyFHZcb6HvbXiU54Fb8DdNzZD136R1tIpdFiiVMtaxyaKyMoIVF5OZVEMHc3mkWuqqUcWCE62FyHh+eSjfxWg==","shasum":"2da601eba4deab16cec00863b1a4445bce300b57","tarball":"https://registry.npmjs.org/vue-class-setup/-/vue-class-setup-1.4.5.tgz","fileCount":118,"unpackedSize":111683,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCSB2OyGm2s6iTZoNVVOV+dkHK2MnIjqgA+o5dz9FJskAIhALFi3SvqHHW+76nQU+J+RsHPHEHHSIfHjktQrizBtRZE"}]},"_npmUser":{"name":"lzxb2015","email":"1340641314@qq.com"},"directories":{},"maintainers":[{"name":"lzxb2015","email":"1340641314@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vue-class-setup_1.4.5_1762498866804_0.4082895890414495"},"_hasShrinkwrap":false}},"maintainers":[{"name":"lzxb2015","email":"1340641314@qq.com"}],"description":"Use class style to write setup and support vue2 and vue3","homepage":"https://github.com/fmfe/vue-class-setup#readme","keywords":["vue-class","vue-class-component","vue-property-decorator","vue-class-composition","vue-class-composition-api"],"repository":{"type":"git","url":"git+ssh://git@github.com/fmfe/vue-class-setup.git"},"author":{"email":"1340641314@qq.com"},"bugs":{"url":"https://github.com/fmfe/vue-class-setup/issues"},"license":"MIT","readme":"# vue-class-setup\n\nUse class style to write setup and support vue2 and vue3\n\n[![Build Status](https://github.com/fmfe/vue-class-setup/workflows/CI/badge.svg)](https://github.com/fmfe/vue-class-setup/actions)\n<a href='https://coveralls.io/github/fmfe/vue-class-setup?branch=main'><img src='https://coveralls.io/repos/github/fmfe/vue-class-setup/badge.svg?branch=main' alt='Coverage Status' /></a>\n[![npm](https://img.shields.io/npm/v/vue-class-setup.svg)](https://www.npmjs.com/package/vue-class-setup)\n[![npm](https://img.shields.io/npm/dm/vue-class-setup.svg)](https://www.npmjs.com/package/vue-class-setup)\n[![npm](https://img.shields.io/npm/dt/vue-class-setup.svg)](https://www.npmjs.com/package/vue-class-setup)\n\n## Why?\n\nUsing class can help you avoid `ref`, `reactive` , `computed` and `withDefaults`, 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\n\n## vue-class-component vs vue-class-setup\n\n**We should deprecate [vue-class-component](https://github.com/vuejs/vue-class-component/issues/569), and use class in setup**\n| List | vue-class-component | vue-class-setup |\n| --- | --- | ----------- |\n| Vue2 | ✅ | ✅ |\n| Vue3 | ❌ | ✅ |\n| Method bind this | ✅ | ✅ |\n| Props type check | ❌ | ✅ |\n| Emit type check | ❌ | ✅ |\n| Watch type check | ❌ | ✅ |\n| Multiple class instances | ❌ | ✅ |\n| Class attribute sets the default value of the prop | ❌ | ✅ |\n\n## Install\n\n```bash\nnpm install vue-class-setup\n# or\nyarn add vue-class-setup\n```\n\n## Quick start\n\n<!-- file:./tests/demo.vue start -->\n\n```vue\n<script lang=\"ts\">\nimport { defineComponent } from 'vue';\nimport { Setup, Context } from 'vue-class-setup';\n\n// Setup and Context must work together\n@Setup\nclass App extends Context {\n    private _value = 0;\n    public get text() {\n        return String(this._value);\n    }\n    public set text(text: string) {\n        this._value = Number(text);\n    }\n    public onClick() {\n        this._value++;\n    }\n}\nexport default defineComponent({\n    // Inject setup\n    ...App.inject(),\n});\n</script>\n<template>\n    <div>\n        <p>{{ text }}</p>\n        <button @click=\"onClick()\"></button>\n    </div>\n</template>\n```\n\n<!-- file:./tests/demo.vue end -->\n\n`Setup` and `Context` collect dependency information together, and convert it into a Vue program after executing the subclass constructor\n\n## Setup\n\nIf the component defines `props`, writing the `class` in the `setup` will cause the `setup` function to create a `class` every time as it executes, which will add costs. So we should avoid writing `class` in `setup` and use `Define` basic class to receive `props` and `emit`.\n\n### Context and Define\n\n`Context` automatic injection `$vm`, `Define` extend from `Context`, and `Define` will automatically inject `$props` and `$emit`, when encapsulating public classes, you may not want to inject props and emit\n\n### Best practices\n\n<!-- file:./tests/base-component-child.vue start -->\n\n```vue\n<script lang=\"ts\">\nimport { defineComponent } from 'vue';\nimport { Setup, Define } from 'vue-class-setup';\n\n// You can create multiple setup class, Only one is shown here\n@Setup\nclass App extends Define<Props, Emit> {\n    // ✨ The default value of the prop can only be initialized in the constructor,\n    // ✨ and cannot be modified later. It is only read-only\n    public readonly dest = '--';\n    // Automatically convert to vue 'computed'\n    public get text() {\n        return String(this.value);\n    }\n    public click(evt: MouseEvent) {\n        this.$emit('click', evt);\n    }\n}\n/**\n * You can directly call the injection method here\n * or manually inject in the setup function\n * <script lang=\"ts\" setup>\n *      const app = new App();\n * <\\/script>\n * <template>\n *      <div>{{ app.text }}</div>\n * </template>\n */\nexport default defineComponent({\n    ...App.inject(),\n});\n</script>\n<script lang=\"ts\" setup>\n// Props and Emits need to be exported\nexport interface Props {\n    value: number;\n    dest?: string;\n}\nexport interface Emit {\n    (event: 'click', evt: MouseEvent): void;\n}\n// Variable reception must be used, otherwise Vue compilation error\n// ❌ const props = defineProps<Props>();\n// ❌ const emit = defineEmits<Emit>();\ndefineProps<Props>(); //  ✅\ndefineEmits<Emit>(); //  ✅\n\n// You should define default values directly on the class\n// ❌ withDefaults(defineProps<Props>(), { dest: '--' });\n// ✅ @Setup\n// ✅ class App extends Define<Props, Emit> {\n// ✅     public readonly dest = '--'\n// ✅ }\n\n// Automatic dependency injection and reactive\n// const app = reactive(new App()); // ❌\n// const app = new App();           // ✅\n</script>\n<template>\n    <button class=\"btn\" @click=\"click($event)\">\n        <span class=\"text\">{{ text }}</span>\n        <span class=\"props-dest\">{{ dest }}</span>\n        <span class=\"props-value\">{{ $props.value }}</span>\n    </button>\n</template>\n```\n\n<!-- file:./tests/base-component-child.vue end -->\n\n### Multiple class instances\n\nWhen the business is complex, multiple instances should be split\n\n<!-- file:./tests/extend.vue start -->\n\n```vue\n<script lang=\"ts\">\nimport { onBeforeMount, onMounted } from 'vue';\nimport { Setup, Context, PassOnTo } from 'vue-class-setup';\n\n@Setup\nclass Base extends Context {\n    public value = 0;\n    public get text() {\n        return String(this.value);\n    }\n    @PassOnTo(onBeforeMount)\n    public init() {\n        this.value++;\n    }\n}\n\n@Setup\nclass Left extends Base {\n    public left = 0;\n    public get text() {\n        return String(`value:${this.value}`);\n    }\n    public init() {\n        super.init();\n        this.value++;\n    }\n    @PassOnTo(onMounted)\n    public initLeft() {\n        this.left++;\n    }\n}\n\n@Setup\nclass Right extends Base {\n    public right = 0;\n    public init() {\n        super.init();\n        this.value++;\n    }\n    @PassOnTo(onMounted)\n    public initLeft() {\n        this.right++;\n    }\n}\n</script>\n<script setup lang=\"ts\">\nconst left = new Left();\nconst right = new Right();\n</script>\n<template>\n    <p class=\"left\">{{ left.text }}</p>\n    <p class=\"right\">{{ right.text }}</p>\n</template>\n```\n\n<!-- file:./tests/extend.vue end -->\n\n### PassOnTo\n\nThis `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\n\n```ts\n@Setup\nclass App extends Define {\n    @PassOnTo(myFunc)\n    public init(name: string) {}\n}\n\nfunction myFunc(callback: (name: string) => void) {\n    // ...\n}\n```\n\nIf `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`\n\n```ts\nimport { Watch } from 'vue';\n\n@Setup\nclass App extends Define {\n    public value = 0;\n    @PassOnTo()\n    private setup() {\n        // You can safely watch, but it is recommended to use the Watch decorator\n        watch(\n            () => this.value,\n            (value) => {\n                // ...\n            }\n        );\n    }\n}\n```\n\n### Watch\n\nIt can correctly identify the type\n\n<!-- file:./tests/watch.vue start -->\n\n```vue\n<script lang=\"ts\">\nimport { Setup, Watch, Context } from 'vue-class-setup';\n\n@Setup\nclass App extends Context {\n    public value = 0;\n    public immediateValue = 0;\n    public onClick() {\n        this.value++;\n    }\n    @Watch('value')\n    public watchValue(value: number, oldValue: number) {\n        if (value > 100) {\n            this.value = 100;\n        }\n    }\n    @Watch('value', { immediate: true })\n    public watchImmediateValue(value: number, oldValue: number | undefined) {\n        if (typeof oldValue === 'undefined') {\n            this.immediateValue = 10;\n        } else {\n            this.immediateValue++;\n        }\n    }\n}\n</script>\n<script setup lang=\"ts\">\nconst app = new App();\n</script>\n<template>\n    <p class=\"value\">{{ app.value }}</p>\n    <p class=\"immediate-value\">{{ app.immediateValue }}</p>\n    <button @click=\"app.onClick()\">Add</button>\n</template>\n```\n\n<!-- file:./tests/watch.vue end -->\n\n## Get the injection object in setup\n\nUseful when `defineExpose`\n\n<!-- file:./tests/use.vue start -->\n\n```vue\n<script lang=\"ts\">\nimport { defineComponent } from 'vue';\nimport { Setup, Context } from 'vue-class-setup';\n\n@Setup\nclass App extends Context {\n    private _value = 0;\n    public get text() {\n        return String(this._value);\n    }\n    public set text(text: string) {\n        this._value = Number(text);\n    }\n    public addValue() {\n        this._value++;\n    }\n}\nexport default defineComponent({\n    ...App.inject(),\n});\n</script>\n<script lang=\"ts\" setup>\nconst app = App.use();\n\ndefineExpose({\n    addValue: app.addValue,\n});\n</script>\n<template>\n    <div>\n        <p class=\"text\">{{ text }}</p>\n        <p class=\"text-eq\">{{ app.text === text }}</p>\n        <button @click=\"addValue\"></button>\n    </div>\n</template>\n```\n\n<!-- file:./tests/use.vue end -->\n\n## Vue compatible\n\n- `getCurrentInstance` returns the proxy object by default\n- `VueInstance` It is not easy to get a Vue instance object type compatible with vue2 and vue3. We make it easy\n\n```ts\nimport {\n    isVue2,\n    isVue3,\n    getCurrentInstance,\n    type VueInstance,\n} from 'vue-class-setup';\n\n// isVue2 -> boolean\n// isVue3 -> boolean\n// getCurrentInstance -> VueInstance\n```\n","readmeFilename":"README.md"}