diff --git a/docs/index.md b/docs/index.md
index 7b11152..f217810 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -8,7 +8,7 @@ features:
- title: 类组件
details: 功能与类型融为一体,无需多次声明类型,独立的属性类型声明,各种HOC组合轻而易举
- title: 自动的依赖注入
- details: 基于动态解析的 injection-js 依赖注入,让使用服务丝般自然
+ details: 基于动态解析的 injection-js 依赖注入,让使用服务丝般顺滑
- title: vue3无ref编程
details: 无需关注ref及其value,正常声明变量,编程体验更自然
---
diff --git a/example/api/http.ts b/example/api/http.ts
deleted file mode 100644
index 50a9f8d..0000000
--- a/example/api/http.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import axios from 'axios'
-
-export const http = axios.create()
-export const HTTP_CLIENT = Symbol()
-
-export function login() {
- return http.get('/login')
-}
diff --git a/example/app.tsx b/example/app.tsx
deleted file mode 100644
index 8939bd6..0000000
--- a/example/app.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import { Component } from '@/di'
-import { VueComponent } from 'vue3-oop'
-import { UserService } from './module/auth/user.service'
-import { Button, Col, ConfigProvider, Row } from 'ant-design-vue'
-import zhCN from 'ant-design-vue/es/locale/zh_CN'
-import { RouterView } from 'vue-router'
-import { RouterService } from './router/router.service'
-import { http, HTTP_CLIENT } from './api/http'
-import { CountService } from './count.service'
-
-@Component({
- providers: [UserService, RouterService, { provide: HTTP_CLIENT, useValue: http }, CountService],
-})
-export class App extends VueComponent {
- constructor(
- private userService: UserService,
- private routerService: RouterService,
- private countService: CountService,
- ) {
- super()
- }
- render() {
- return (
-
- 全局服务
-
-
-
- {this.countService.count}
-
-
-
-
-
- )
- }
-}
diff --git a/example/common/decorators/catch.decorator.ts b/example/common/decorators/catch.decorator.ts
deleted file mode 100644
index ca0c0ee..0000000
--- a/example/common/decorators/catch.decorator.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { message } from 'ant-design-vue'
-
-export function CatchLoading(loadingKey?: string): MethodDecorator {
- return function (target: any, key: string | symbol, desc: PropertyDescriptor) {
- const value = desc.value
- if (typeof value !== 'function') {
- throw new TypeError(`${key as string} prop should be a function`)
- }
- desc.value = async function (this: any, ...args: any[]) {
- if (loadingKey && this[loadingKey]) return
- if (loadingKey) this[loadingKey] = true
- try {
- await value.apply(this, args)
- } catch (e: any) {
- console.error(e)
- message.error(e.message)
- } finally {
- if (loadingKey) this[loadingKey] = false
- }
- }
- }
-}
diff --git a/example/layout/default.layout.tsx b/example/layout/default.layout.tsx
deleted file mode 100644
index 1dc586e..0000000
--- a/example/layout/default.layout.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import { VueComponent } from '@/index'
-import { RouterView } from 'vue-router'
-
-export default class DefaultLayout extends VueComponent {
- render() {
- return
- }
-}
diff --git a/example/main.tsx b/example/main.tsx
index f6d3817..01dd025 100644
--- a/example/main.tsx
+++ b/example/main.tsx
@@ -1,70 +1,73 @@
import '@abraham/reflection'
-import { Component, Computed, Hook, Link, Mut, VueComponent } from 'vue3-oop'
-import { createApp, watchSyncEffect } from 'vue'
-import './theme/app.css'
-import { CountService } from './count.service'
-import { SizeService } from './size.service'
+import { Component, Computed, Hook, Mut, VueComponent, VueService } from 'vue3-oop'
+import { createApp } from 'vue'
-class Child extends VueComponent {
- render() {
- console.log('render')
- return (
-
- 111
-
{this.context.slots.default?.()}
-
- )
+const debounce = (delay: number) => {
+ let timeout: number | undefined
+ return (track: any, trigger: any) => {
+ let value: any
+ return {
+ get() {
+ track()
+ return value
+ },
+ set(newValue: any) {
+ clearTimeout(timeout)
+ timeout = window.setTimeout(() => {
+ value = newValue
+ trigger()
+ }, delay)
+ },
+ }
}
}
-@Component()
+class CountService extends VueService {
+ @Mut() count = 1
+}
+
class Home extends VueComponent {
- constructor(private countService: CountService, private sizeService: SizeService) {
- super()
- watchSyncEffect(() => this.count > 2)
- }
+ @Mut(debounce(1000)) _count = ''
- @Mut() count = 1
+ @Mut() obj = { name: 123 }
@Computed()
get double() {
- return this.count * 2
+ return this._count
+ }
+ set double(val: string) {
+ this._count = val.toUpperCase()
}
- list = new Array(10).fill(1)
-
- @Link() aaa: Child[]
@Hook('Mounted')
mounted() {
- console.log(this.aaa)
+ console.log('mounted')
+ }
+
+ render() {
+ console.log(this.obj)
+ console.log('render')
+ return
}
+}
+@Component()
+class Home1 extends Home {
+ constructor(private cs: CountService) {
+ super()
+ console.log(cs)
+ }
+ @Mut() count1 = 111
render() {
return (
-
-
- 11111
-
-
count: {this.countService.count}
-
-
-
- 矩形大小: 宽度: {this.sizeService.x} 长度: {this.sizeService.y}
-
-
+
+
this.cs.count++}>{this.cs.count}
+ this.count1++}>1111{this.count1}
+ {super.render()}
)
}
}
-const app = createApp(Home)
+const app = createApp(Home1)
app.mount('#app')
diff --git a/example/module/auth/login.view.tsx b/example/module/auth/login.view.tsx
deleted file mode 100644
index 6ee60f5..0000000
--- a/example/module/auth/login.view.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import { Component, VueComponent } from '@/index'
-import { UserService } from './user.service'
-import { Button, Col, Form, Input, Row } from 'ant-design-vue'
-import { Mut } from '@/decorators/mut'
-import { CatchLoading } from '../../common/decorators/catch.decorator'
-import { Autobind } from '@/helper'
-import { CountService } from '../../count.service'
-import { SkipSelf } from 'injection-js'
-import { VNodeChild } from 'vue'
-
-@Component({
- providers: [CountService],
-})
-export default class LoginView extends VueComponent {
- constructor(
- private userService: UserService,
- @SkipSelf() private parentCountService: CountService,
- private countService: CountService,
- ) {
- super()
- }
- @Mut() loading = false
- @Mut() model = {
- name: '',
- pwd: '',
- }
- rules = {
- name: [{ required: true, message: '请输入账号' }],
- pwd: [{ required: true, message: '请输入密码' }],
- }
-
- @Autobind()
- @CatchLoading('loading')
- async submit() {
- await this.userService.login(this.model)
- }
-
- render() {
- const hslots: HomeChild
['props']['v-slots'] = {
- $stable: true,
- item(): VNodeChild {
- return 111
- },
- }
- return (
-
-
- 全局的状态: {this.parentCountService.count}
- 局部的状态
-
-
-
- {this.countService.count}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
- }
-}
-interface HomeChild_Props {
- list?: DataItem[]
- title?: string | ((list: DataItem[]) => VNodeChild)
- /**
- * 插槽
- */
- slots?: {
- item(): VNodeChild
- }
-}
-class HomeChild extends VueComponent> {
- render() {
- return
- }
-}
diff --git a/example/module/auth/user.service.ts b/example/module/auth/user.service.ts
deleted file mode 100644
index a4e5d38..0000000
--- a/example/module/auth/user.service.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Hook, Mut, VueService } from '@/index'
-import { Inject, Injectable } from 'injection-js'
-import { RouterService } from '../../router/router.service'
-import { AxiosInstance } from 'axios'
-import { HTTP_CLIENT } from '../../api/http'
-
-@Injectable()
-export class UserService extends VueService {
- constructor(private routerService: RouterService, @Inject(HTTP_CLIENT) private httpService: AxiosInstance) {
- super()
- this.guardHttp()
- this.guardRouter()
- }
- @Mut() token = ''
-
- private _requestGuard: number
-
- guardHttp() {
- this._requestGuard = this.httpService.interceptors.request.use((config) => {
- return config
- })
- }
-
- guardRouter() {
- this.routerService.router.beforeEach(async (to, from) => {
- if (to.path === '/login' && this.token) return { path: '/' }
- if (to.path !== '/login' && !this.token) return { path: '/login' }
- })
- }
-
- @Hook('BeforeUnmount')
- unmount() {
- this.httpService.interceptors.request.eject(this._requestGuard)
- }
-
- async login(model: any) {
- this.token = await new Promise((resolve) => setTimeout(resolve, 1000, 'token'))
- await this.routerService.router.replace('/')
- }
-}
diff --git a/example/module/home/home.view.tsx b/example/module/home/home.view.tsx
deleted file mode 100644
index 5873e79..0000000
--- a/example/module/home/home.view.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Component, VueComponent } from '@/index'
-import { CountService } from '../../count.service'
-import { Optional, SkipSelf } from 'injection-js'
-import { Button, Col, Row } from 'ant-design-vue'
-import { watch } from 'vue'
-import { focusDirective } from '../../focus.directive'
-
-@Component({
- providers: [CountService],
-})
-export default class HomeView extends VueComponent {
- static directives = {
- focus: focusDirective,
- }
- constructor(
- @SkipSelf() private parentCountService: CountService,
- private countService: CountService,
- @Optional() private aaa: string,
- ) {
- super()
- watch(
- () => this.parentCountService.count,
- () => (countService.count = parentCountService.count),
- {
- immediate: true,
- },
- )
- }
- render() {
- return (
- <>
- 全局的状态: {this.parentCountService.count}
- 局部的状态
-
-
-
- {this.countService.count}
-
-
-
-
- >
- )
- }
-}
diff --git a/example/router/router.service.ts b/example/router/router.service.ts
deleted file mode 100644
index 95a68ee..0000000
--- a/example/router/router.service.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Injectable } from 'injection-js'
-import { createRouter, createWebHistory } from 'vue-router'
-import { routes } from './routes'
-import { getCurrentApp, VueService } from '@/index'
-
-@Injectable()
-export class RouterService extends VueService {
- history = createWebHistory()
- router = createRouter({
- history: this.history,
- routes: routes,
- })
- app = getCurrentApp()!
- get currentRoute() {
- return this.router.currentRoute.value
- }
-
- constructor() {
- super()
- this.app.use(this.router)
- }
-}
diff --git a/example/router/routes.ts b/example/router/routes.ts
deleted file mode 100644
index 066e8ca..0000000
--- a/example/router/routes.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { RouteRecordRaw } from 'vue-router'
-
-export const routes: RouteRecordRaw[] = [
- {
- path: '/login',
- component: () => import('../module/auth/login.view'),
- },
- {
- path: '/',
- component: () => import('../layout/default.layout'),
- children: [
- {
- path: '/',
- component: () => import('../module/home/home.view'),
- },
- ],
- },
-]
diff --git a/example/theme/app.css b/example/theme/app.css
deleted file mode 100644
index a8b2ee8..0000000
--- a/example/theme/app.css
+++ /dev/null
@@ -1,5 +0,0 @@
-html,
-body,
-#app {
- height: 100%;
-}
diff --git a/package.json b/package.json
index c918fb2..4580766 100644
--- a/package.json
+++ b/package.json
@@ -64,12 +64,12 @@
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"@vitejs/plugin-vue": "^2.0.1",
+ "@vue/reactivity": "^3.2.26",
"@vue/runtime-core": "^3.2.26",
"@vue/test-utils": "^2.0.0-rc.18",
"@vue3-oop/plugin-vue-jsx": "^1.4.0",
"ant-design-vue": "^3.0.0-alpha.11",
"autobind-decorator": "^2.4.0",
- "axios": "^0.24.0",
"c8": "^7.11.0",
"commitizen": "^4.2.4",
"commitlint-config-cz": "^0.13.3",
@@ -78,7 +78,7 @@
"eslint": "^8.6.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
- "happy-dom": "^2.25.1",
+ "happy-dom": "^2.25.2",
"injection-js": "^2.4.0",
"lint-staged": "^12.1.7",
"lodash-es": "^4.17.21",
@@ -86,13 +86,13 @@
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
- "sass": "^1.47.0",
+ "sass": "^1.48.0",
"standard-version": "^9.3.2",
"tslib": "^2.3.1",
"typescript": "^4.5.4",
- "vite": "^2.7.10",
+ "vite": "^2.7.12",
"vitepress": "^0.21.4",
- "vitest": "^0.0.141",
+ "vitest": "^0.1.16",
"vue": "^3.2.26",
"vue-router": "^4.0.12"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3f6c292..909bfc8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,12 +14,12 @@ specifiers:
'@typescript-eslint/eslint-plugin': ^5.9.1
'@typescript-eslint/parser': ^5.9.1
'@vitejs/plugin-vue': ^2.0.1
+ '@vue/reactivity': ^3.2.26
'@vue/runtime-core': ^3.2.26
'@vue/test-utils': ^2.0.0-rc.18
'@vue3-oop/plugin-vue-jsx': ^1.4.0
ant-design-vue: ^3.0.0-alpha.11
autobind-decorator: ^2.4.0
- axios: ^0.24.0
c8: ^7.11.0
commitizen: ^4.2.4
commitlint-config-cz: ^0.13.3
@@ -28,7 +28,7 @@ specifiers:
eslint: ^8.6.0
eslint-config-prettier: ^8.3.0
eslint-plugin-prettier: ^4.0.0
- happy-dom: ^2.25.1
+ happy-dom: ^2.25.2
injection-js: ^2.4.0
lint-staged: ^12.1.7
lodash-es: ^4.17.21
@@ -36,13 +36,13 @@ specifiers:
npm-run-all: ^4.1.5
prettier: ^2.5.1
rimraf: ^3.0.2
- sass: ^1.47.0
+ sass: ^1.48.0
standard-version: ^9.3.2
tslib: ^2.3.1
typescript: ^4.5.4
- vite: ^2.7.10
+ vite: ^2.7.12
vitepress: ^0.21.4
- vitest: ^0.0.141
+ vitest: ^0.1.16
vue: ^3.2.26
vue-router: ^4.0.12
@@ -57,13 +57,13 @@ devDependencies:
'@types/swagger-schema-official': 2.0.22
'@typescript-eslint/eslint-plugin': 5.9.1_b7b2e42b32ee097737cd3e626b10847b
'@typescript-eslint/parser': 5.9.1_eslint@8.6.0+typescript@4.5.4
- '@vitejs/plugin-vue': 2.0.1_vite@2.7.10+vue@3.2.26
+ '@vitejs/plugin-vue': 2.0.1_vite@2.7.12+vue@3.2.26
+ '@vue/reactivity': 3.2.26
'@vue/runtime-core': 3.2.26
'@vue/test-utils': 2.0.0-rc.18_vue@3.2.26
'@vue3-oop/plugin-vue-jsx': 1.4.0_typescript@4.5.4
ant-design-vue: 3.0.0-alpha.14_vue@3.2.26
autobind-decorator: 2.4.0
- axios: 0.24.0
c8: 7.11.0
commitizen: 4.2.4_@types+node@17.0.6
commitlint-config-cz: 0.13.3
@@ -72,7 +72,7 @@ devDependencies:
eslint: 8.6.0
eslint-config-prettier: 8.3.0_eslint@8.6.0
eslint-plugin-prettier: 4.0.0_1c588f61426b1faf18812943f1678311
- happy-dom: 2.25.1
+ happy-dom: 2.25.2
injection-js: 2.4.0
lint-staged: 12.1.7
lodash-es: 4.17.21
@@ -80,13 +80,13 @@ devDependencies:
npm-run-all: 4.1.5
prettier: 2.5.1
rimraf: 3.0.2
- sass: 1.47.0
+ sass: 1.48.0
standard-version: 9.3.2
tslib: 2.3.1
typescript: 4.5.4
- vite: 2.7.10_sass@1.47.0
- vitepress: 0.21.4_sass@1.47.0
- vitest: 0.0.141_69668438cdc6d44ee4b86ac6ca4d551c
+ vite: 2.7.12_sass@1.48.0
+ vitepress: 0.21.4_sass@1.48.0
+ vitest: 0.1.16_6385a6dc872cf54928889045b2a24481
vue: 3.2.26
vue-router: 4.0.12_vue@3.2.26
@@ -870,13 +870,13 @@ packages:
/@types/concat-stream/1.6.1:
resolution: {integrity: sha1-JLz8EB7PaOiGqu3OYN/XS2MqG3Q=, tarball: '@types/concat-stream/download/@types/concat-stream-1.6.1.tgz'}
dependencies:
- '@types/node': 17.0.6
+ '@types/node': 17.0.8
dev: true
/@types/form-data/0.0.33:
resolution: {integrity: sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=, tarball: '@types/form-data/download/@types/form-data-0.0.33.tgz'}
dependencies:
- '@types/node': 17.0.6
+ '@types/node': 17.0.8
dev: true
/@types/istanbul-lib-coverage/2.0.4:
@@ -924,6 +924,10 @@ packages:
resolution: {integrity: sha512-+XBAjfZmmivILUzO0HwBJoYkAyyySSLg5KCGBDFLomJo0sV6szvVLAf4ANZZ0pfWzgEds5KmGLG9D5hfEqOhaA==, tarball: '@types/node/download/@types/node-17.0.6.tgz'}
dev: true
+ /@types/node/17.0.8:
+ resolution: {integrity: sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==, tarball: '@types/node/download/@types/node-17.0.8.tgz'}
+ dev: true
+
/@types/node/8.10.66:
resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==, tarball: '@types/node/download/@types/node-8.10.66.tgz'}
dev: true
@@ -1074,14 +1078,14 @@ packages:
eslint-visitor-keys: 3.1.0
dev: true
- /@vitejs/plugin-vue/2.0.1_vite@2.7.10+vue@3.2.26:
+ /@vitejs/plugin-vue/2.0.1_vite@2.7.12+vue@3.2.26:
resolution: {integrity: sha512-wtdMnGVvys9K8tg+DxowU1ytTrdVveXr3LzdhaKakysgGXyrsfaeds2cDywtvujEASjWOwWL/OgWM+qoeM8Plg==, tarball: '@vitejs/plugin-vue/download/@vitejs/plugin-vue-2.0.1.tgz'}
engines: {node: '>=12.0.0'}
peerDependencies:
vite: ^2.5.10
vue: ^3.2.25
dependencies:
- vite: 2.7.10_sass@1.47.0
+ vite: 2.7.12_sass@1.48.0
vue: 3.2.26
dev: true
@@ -1436,14 +1440,6 @@ packages:
engines: {node: '>=8.10', npm: '>=6.4.1'}
dev: true
- /axios/0.24.0:
- resolution: {integrity: sha1-gE5voeS5xSiFAd2d/1anoJQNINY=, tarball: axios/download/axios-0.24.0.tgz}
- dependencies:
- follow-redirects: 1.14.6
- transitivePeerDependencies:
- - debug
- dev: true
-
/balanced-match/1.0.2:
resolution: {integrity: sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=, tarball: balanced-match/download/balanced-match-1.0.2.tgz}
dev: true
@@ -2946,16 +2942,6 @@ packages:
resolution: {integrity: sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==, tarball: flatted/download/flatted-3.2.4.tgz}
dev: true
- /follow-redirects/1.14.6:
- resolution: {integrity: sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==, tarball: follow-redirects/download/follow-redirects-1.14.6.tgz}
- engines: {node: '>=4.0'}
- peerDependencies:
- debug: '*'
- peerDependenciesMeta:
- debug:
- optional: true
- dev: true
-
/foreground-child/2.0.0:
resolution: {integrity: sha1-cbMoAMnxWqjy+D9Ka9m/812GGlM=, tarball: foreground-child/download/foreground-child-2.0.0.tgz}
engines: {node: '>=8.0.0'}
@@ -3304,8 +3290,8 @@ packages:
uglify-js: 3.14.5
dev: true
- /happy-dom/2.25.1:
- resolution: {integrity: sha512-HGNjJ0rROjpRvGUaZ9exj9hbR2rTeKJyhswmr+YhRr/jQuYmXdokq0oHVUkqo2AkJRnF/8FEWDENdrLorib8lA==, tarball: happy-dom/download/happy-dom-2.25.1.tgz}
+ /happy-dom/2.25.2:
+ resolution: {integrity: sha512-PEKxqE7v04J3t6hESxmWwbeimJSNpw+10OyG2dqA8uUsm35xqM2fL0KoppQHC2BRuPKy43rmH+ZHEXMuGz3XEQ==, tarball: happy-dom/download/happy-dom-2.25.2.tgz}
dependencies:
he: 1.2.0
node-fetch: 2.6.6
@@ -3368,7 +3354,7 @@ packages:
dev: true
/he/1.2.0:
- resolution: {integrity: sha1-hK5l+n6vsWX922FWauFLrwVmTw8=, tarball: he/download/he-1.2.0.tgz}
+ resolution: {integrity: sha1-hK5l+n6vsWX922FWauFLrwVmTw8=, tarball: he/download/he-1.2.0.tgz?cache=0&sync_timestamp=1632822734781&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhe%2Fdownload%2Fhe-1.2.0.tgz}
hasBin: true
dev: true
@@ -3569,8 +3555,8 @@ packages:
ci-info: 1.6.0
dev: true
- /is-core-module/2.8.0:
- resolution: {integrity: sha1-AyEzbD0JJeSX/Zf12VyxFKXM1Ug=, tarball: is-core-module/download/is-core-module-2.8.0.tgz}
+ /is-core-module/2.8.1:
+ resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==, tarball: is-core-module/download/is-core-module-2.8.1.tgz}
dependencies:
has: 1.0.3
dev: true
@@ -3808,7 +3794,7 @@ packages:
/jsonfile/4.0.0:
resolution: {integrity: sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=, tarball: jsonfile/download/jsonfile-4.0.0.tgz}
optionalDependencies:
- graceful-fs: 4.2.8
+ graceful-fs: 4.2.9
dev: true
/jsonfile/6.1.0:
@@ -3897,7 +3883,7 @@ packages:
resolution: {integrity: sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=, tarball: load-json-file/download/load-json-file-1.1.0.tgz}
engines: {node: '>=0.10.0'}
dependencies:
- graceful-fs: 4.2.8
+ graceful-fs: 4.2.9
parse-json: 2.2.0
pify: 2.3.0
pinkie-promise: 2.0.1
@@ -4177,7 +4163,7 @@ packages:
dev: true
/mime-types/2.1.34:
- resolution: {integrity: sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==, tarball: mime-types/download/mime-types-2.1.34.tgz?cache=0&sync_timestamp=1636432606654&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fmime-types%2Fdownload%2Fmime-types-2.1.34.tgz}
+ resolution: {integrity: sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==, tarball: mime-types/download/mime-types-2.1.34.tgz?cache=0&sync_timestamp=1636436454904&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fmime-types%2Fdownload%2Fmime-types-2.1.34.tgz}
engines: {node: '>= 0.6'}
dependencies:
mime-db: 1.51.0
@@ -4254,8 +4240,8 @@ packages:
resolution: {integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=, tarball: mute-stream/download/mute-stream-0.0.7.tgz}
dev: true
- /nanoid/3.1.30:
- resolution: {integrity: sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==, tarball: nanoid/download/nanoid-3.1.30.tgz}
+ /nanoid/3.1.32:
+ resolution: {integrity: sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw==, tarball: nanoid/download/nanoid-3.1.32.tgz}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: true
@@ -4301,7 +4287,7 @@ packages:
engines: {node: '>=10'}
dependencies:
hosted-git-info: 4.0.2
- is-core-module: 2.8.0
+ is-core-module: 2.8.1
semver: 7.3.5
validate-npm-package-license: 3.0.4
dev: true
@@ -4604,7 +4590,7 @@ packages:
resolution: {integrity: sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=, tarball: path-type/download/path-type-1.1.0.tgz}
engines: {node: '>=0.10.0'}
dependencies:
- graceful-fs: 4.2.8
+ graceful-fs: 4.2.9
pify: 2.3.0
pinkie-promise: 2.0.1
dev: true
@@ -4626,7 +4612,7 @@ packages:
dev: true
/picocolors/1.0.0:
- resolution: {integrity: sha1-y1vcdP8/UYkiNur3nWi8RFZKuBw=, tarball: picocolors/download/picocolors-1.0.0.tgz}
+ resolution: {integrity: sha1-y1vcdP8/UYkiNur3nWi8RFZKuBw=, tarball: picocolors/download/picocolors-1.0.0.tgz?cache=0&sync_timestamp=1634097134444&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fpicocolors%2Fdownload%2Fpicocolors-1.0.0.tgz}
dev: true
/picomatch/2.3.1:
@@ -4666,7 +4652,7 @@ packages:
resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==, tarball: postcss/download/postcss-8.4.5.tgz}
engines: {node: ^10 || ^12 || >=14}
dependencies:
- nanoid: 3.1.30
+ nanoid: 3.1.32
picocolors: 1.0.0
source-map-js: 1.0.1
dev: true
@@ -4732,8 +4718,8 @@ packages:
engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
dev: true
- /qs/6.10.2:
- resolution: {integrity: sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==, tarball: qs/download/qs-6.10.2.tgz}
+ /qs/6.10.3:
+ resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==, tarball: qs/download/qs-6.10.3.tgz}
engines: {node: '>=0.6'}
dependencies:
side-channel: 1.0.4
@@ -4920,8 +4906,17 @@ packages:
/resolve/1.20.0:
resolution: {integrity: sha1-YpoBP7P3B1XW8LeTXMHCxTeLGXU=, tarball: resolve/download/resolve-1.20.0.tgz}
dependencies:
- is-core-module: 2.8.0
+ is-core-module: 2.8.1
+ path-parse: 1.0.7
+ dev: true
+
+ /resolve/1.21.0:
+ resolution: {integrity: sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==, tarball: resolve/download/resolve-1.21.0.tgz}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.8.1
path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
dev: true
/responselike/1.0.2:
@@ -4969,8 +4964,8 @@ packages:
glob: 7.2.0
dev: true
- /rollup/2.62.0:
- resolution: {integrity: sha512-cJEQq2gwB0GWMD3rYImefQTSjrPYaC6s4J9pYqnstVLJ1CHa/aZNVkD4Epuvg4iLeMA4KRiq7UM7awKK6j7jcw==, tarball: rollup/download/rollup-2.62.0.tgz}
+ /rollup/2.64.0:
+ resolution: {integrity: sha512-+c+lbw1lexBKSMb1yxGDVfJ+vchJH3qLbmavR+awDinTDA2C5Ug9u7lkOzj62SCu0PKUExsW36tpgW7Fmpn3yQ==, tarball: rollup/download/rollup-2.64.0.tgz}
engines: {node: '>=10.0.0'}
hasBin: true
optionalDependencies:
@@ -5013,8 +5008,8 @@ packages:
resolution: {integrity: sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=, tarball: safer-buffer/download/safer-buffer-2.1.2.tgz}
dev: true
- /sass/1.47.0:
- resolution: {integrity: sha512-GtXwvwgD7/6MLUZPnlA5/8cdRgC9SzT5kAnnJMRmEZQFRE3J56Foswig4NyyyQGsnmNvg6EUM/FP0Pe9Y2zywQ==, tarball: sass/download/sass-1.47.0.tgz}
+ /sass/1.48.0:
+ resolution: {integrity: sha512-hQi5g4DcfjcipotoHZ80l7GNJHGqQS5LwMBjVYB/TaT0vcSSpbgM8Ad7cgfsB2M0MinbkEQQPO9+sjjSiwxqmw==, tarball: sass/download/sass-1.48.0.tgz}
engines: {node: '>=8.9.0'}
hasBin: true
dependencies:
@@ -5399,6 +5394,11 @@ packages:
engines: {node: '>=12'}
dev: true
+ /supports-preserve-symlinks-flag/1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, tarball: supports-preserve-symlinks-flag/download/supports-preserve-symlinks-flag-1.0.0.tgz}
+ engines: {node: '>= 0.4'}
+ dev: true
+
/svg-tags/1.0.0:
resolution: {integrity: sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=, tarball: svg-tags/download/svg-tags-1.0.0.tgz}
dev: true
@@ -5458,7 +5458,7 @@ packages:
http-basic: 8.1.3
http-response-object: 3.0.2
promise: 8.1.0
- qs: 6.10.2
+ qs: 6.10.3
dev: true
/through/2.3.8:
@@ -5714,8 +5714,8 @@ packages:
spdx-expression-parse: 3.0.1
dev: true
- /vite/2.7.10_sass@1.47.0:
- resolution: {integrity: sha512-KEY96ntXUid1/xJihJbgmLZx7QSC2D4Tui0FdS0Old5OokYzFclcofhtxtjDdGOk/fFpPbHv9yw88+rB93Tb8w==, tarball: vite/download/vite-2.7.10.tgz}
+ /vite/2.7.12_sass@1.48.0:
+ resolution: {integrity: sha512-KvPYToRQWhRfBeVkyhkZ5hASuHQkqZUUdUcE3xyYtq5oYEPIJ0h9LWiWTO6v990glmSac2cEPeYeXzpX5Z6qKQ==, tarball: vite/download/vite-2.7.12.tgz}
engines: {node: '>=12.2.0'}
hasBin: true
peerDependencies:
@@ -5732,23 +5732,23 @@ packages:
dependencies:
esbuild: 0.13.15
postcss: 8.4.5
- resolve: 1.20.0
- rollup: 2.62.0
- sass: 1.47.0
+ resolve: 1.21.0
+ rollup: 2.64.0
+ sass: 1.48.0
optionalDependencies:
fsevents: 2.3.2
dev: true
- /vitepress/0.21.4_sass@1.47.0:
+ /vitepress/0.21.4_sass@1.48.0:
resolution: {integrity: sha512-r7zAOp65T3/3tX6tD1QfQaqHnPzr2Xkq0Cw8gjXDk2MGZ7e3BMwow1wRn/k1D2lBZ2kEE2vQCC2/zfoCzrDRuw==, tarball: vitepress/download/vitepress-0.21.4.tgz}
engines: {node: '>=12.0.0'}
hasBin: true
dependencies:
'@docsearch/css': 3.0.0-alpha.42
'@docsearch/js': 3.0.0-alpha.42
- '@vitejs/plugin-vue': 2.0.1_vite@2.7.10+vue@3.2.26
+ '@vitejs/plugin-vue': 2.0.1_vite@2.7.12+vue@3.2.26
prismjs: 1.26.0
- vite: 2.7.10_sass@1.47.0
+ vite: 2.7.12_sass@1.48.0
vue: 3.2.26
transitivePeerDependencies:
- '@algolia/client-search'
@@ -5760,8 +5760,8 @@ packages:
- stylus
dev: true
- /vitest/0.0.141_69668438cdc6d44ee4b86ac6ca4d551c:
- resolution: {integrity: sha512-CQwNWGbifAs5OrG1MXyiveeFT3KYpU/UZiZzNUR5ZHMUWKam9OeoDX0U3sFuyaERp/0b2vhoL0oaMccY2PJPSQ==, tarball: vitest/download/vitest-0.0.141.tgz}
+ /vitest/0.1.16_6385a6dc872cf54928889045b2a24481:
+ resolution: {integrity: sha512-fBzazhZPovI9iDCQ3NsL0tdspbhA3ZHne1U/YDKoCRXndrYy9rG/nsimstKzwnaTwg80xn7Zvpmgd/uEgdch1Q==, tarball: vitest/download/vitest-0.1.16.tgz}
engines: {node: '>=14.14.0'}
hasBin: true
peerDependencies:
@@ -5783,11 +5783,11 @@ packages:
'@types/chai-subset': 1.3.3
c8: 7.11.0
chai: 4.3.4
- happy-dom: 2.25.1
+ happy-dom: 2.25.2
local-pkg: 0.4.1
tinypool: 0.1.1
tinyspy: 0.2.8
- vite: 2.7.10_sass@1.47.0
+ vite: 2.7.12_sass@1.48.0
transitivePeerDependencies:
- less
- sass
diff --git a/src/decorators/computed.ts b/src/decorators/computed.ts
index aaba709..490beec 100644
--- a/src/decorators/computed.ts
+++ b/src/decorators/computed.ts
@@ -1,28 +1,23 @@
import { computed } from 'vue'
import { Hanlder } from '../type'
-import { getProtoMetadata } from '../helper'
+import { createDecorator, getProtoMetadata } from './util'
-interface ComputedItem {
- key: string | symbol
- desc: PropertyDescriptor
-}
+export const Computed: ComputedDecorator = createDecorator('Computed')
-const MetadataKey = Symbol('Computed')
-export function Computed(): MethodDecorator {
- return function (target: any, key: string | symbol) {
- let list: (string | symbol)[] = Reflect.getMetadata(MetadataKey, target) || []
- list = list.slice()
- const hasItem = list.find((k) => k === key)
- if (!hasItem) list.push(key)
- Reflect.defineMetadata(MetadataKey, list, target)
- }
+export interface ComputedDecorator {
+ (): MethodDecorator
+ /**
+ * @param shallow 是否是浅层响应式
+ */
+ MetadataKey: string | symbol
}
function handler(targetThis: Record) {
- const list: ComputedItem[] = getProtoMetadata(targetThis, MetadataKey, true)
+ const list = getProtoMetadata(targetThis, Computed.MetadataKey, true)
if (!list || !list.length) return
for (const item of list) {
const desc = item.desc
+ if (!desc) continue
const keyVal = computed({
get: () => desc.get?.call(targetThis),
set: (v: any) => desc.set?.call(targetThis, v),
diff --git a/src/decorators/hook.ts b/src/decorators/hook.ts
index 3ad5457..d4bb5ec 100644
--- a/src/decorators/hook.ts
+++ b/src/decorators/hook.ts
@@ -13,12 +13,7 @@ import {
onUpdated,
} from 'vue'
import { Hanlder } from '../type'
-import { getProtoMetadata } from '../helper'
-
-interface HookItem {
- key: string | symbol
- lifecycle: Lifecycle
-}
+import { createDecorator, getProtoMetadata } from './util'
type Lifecycle =
| 'BeforeMount'
@@ -34,24 +29,19 @@ type Lifecycle =
| 'RenderTriggered'
| 'ServerPrefetch'
-const MetadataKey = Symbol('Hook')
+export const Hook: HookDecorator = createDecorator('Hook')
-export function Hook(lifecycle: Lifecycle): MethodDecorator {
- return function (target: any, key: string | symbol) {
- let list: HookItem[] = Reflect.getMetadata(MetadataKey, target) || []
- list = list.slice()
- const hasItem = list.find((k) => k.key === key && k.lifecycle === lifecycle)
- if (!hasItem) list.push({ key, lifecycle })
- Reflect.defineMetadata(MetadataKey, list, target)
- }
+export interface HookDecorator {
+ (lifecycle: Lifecycle): MethodDecorator
+ MetadataKey: string | symbol
}
function handler(targetThis: any) {
- const list: HookItem[] = getProtoMetadata(targetThis, MetadataKey)
+ const list = getProtoMetadata(targetThis, Hook.MetadataKey)
if (!list || !list.length) return
for (const item of list) {
let vueFn: any
- switch (item.lifecycle) {
+ switch (item.options) {
case 'BeforeMount':
vueFn = onBeforeMount
break
diff --git a/src/decorators/link.ts b/src/decorators/link.ts
index 387e61d..b58eefb 100644
--- a/src/decorators/link.ts
+++ b/src/decorators/link.ts
@@ -1,28 +1,24 @@
import { getCurrentInstance } from 'vue'
import { Hanlder } from '../type'
-import { getProtoMetadata } from '../helper'
+import { createDecorator, getProtoMetadata } from './util'
-const MetadataKey = Symbol('Link')
-export function Link(): PropertyDecorator {
- return function (target: any, key: string | symbol) {
- let list: (string | symbol)[] = Reflect.getMetadata(MetadataKey, target) || []
- list = list.slice()
- const hasItem = list.find((k) => k === key)
- if (!hasItem) list.push(key)
- Reflect.defineMetadata(MetadataKey, list, target)
- }
+export const Link: LinkDecorator = createDecorator('Link')
+export interface LinkDecorator {
+ (refName?: string): PropertyDecorator
+ MetadataKey: symbol | string
}
function handler(targetThis: Record) {
- const list: (string | symbol)[] = getProtoMetadata(targetThis, MetadataKey)
+ const list = getProtoMetadata(targetThis, Link.MetadataKey)
if (!list || !list.length) return
for (const item of list) {
+ const { key, options } = item
const instance = getCurrentInstance()
- Object.defineProperty(targetThis, item, {
+ Object.defineProperty(targetThis, key, {
enumerable: true,
configurable: true,
get() {
- return instance?.refs[item as string]
+ return instance?.refs?.[(options || key) as string]
},
})
}
diff --git a/src/decorators/mut.ts b/src/decorators/mut.ts
index 559cc49..d0549c3 100644
--- a/src/decorators/mut.ts
+++ b/src/decorators/mut.ts
@@ -1,25 +1,39 @@
-import { ref } from 'vue'
+import { customRef, Ref, ref, shallowRef } from 'vue'
import { Hanlder } from '../type'
-import { getProtoMetadata } from '../helper'
+import { createDecorator, getProtoMetadata } from './util'
-const MetadataKey = Symbol('Mut')
+export const Mut: MutDecorator = createDecorator('Mut')
-export function Mut(): PropertyDecorator {
- return function (target: any, key: string | symbol) {
- let list: (string | symbol)[] = Reflect.getMetadata(MetadataKey, target) || []
- list = list.slice()
- const hasItem = list.find((k) => k === key)
- if (!hasItem) list.push(key)
- Reflect.defineMetadata(MetadataKey, list, target)
- }
+type MutOptions = void | true | Parameters[0]
+type RefFactory = Parameters[0]
+export interface MutDecorator {
+ (): PropertyDecorator
+ /**
+ * @param shallow 是否是浅层响应式
+ */
+ (shallow: true): PropertyDecorator
+ /**
+ * 自定义ref 的实现
+ * @param refFactory
+ */
+ (refFactory: RefFactory): PropertyDecorator
+ MetadataKey: string | symbol
}
-function handler(targetThis: Record) {
- const list: (string | symbol)[] = getProtoMetadata(targetThis, MetadataKey)
+function handler(targetThis: Record) {
+ const list = getProtoMetadata(targetThis, Mut.MetadataKey)
if (!list || !list.length) return
for (const item of list) {
- const keyVal = ref()
- Object.defineProperty(targetThis, item, {
+ const { options, key } = item
+ let keyVal: Ref
+ if (options === true) {
+ keyVal = shallowRef()
+ } else if (typeof options === 'function') {
+ keyVal = customRef(options)
+ } else {
+ keyVal = ref()
+ }
+ Object.defineProperty(targetThis, key, {
enumerable: true,
configurable: true,
get() {
@@ -36,10 +50,3 @@ export const MutHandler: Hanlder = {
key: 'Mut',
handler,
}
-
-/**
- * @deprecated 因与vue的ref冲突,故改名为 Mut
- */
-export function Ref() {
- return Mut()
-}
diff --git a/src/decorators/util.ts b/src/decorators/util.ts
new file mode 100644
index 0000000..164ba2a
--- /dev/null
+++ b/src/decorators/util.ts
@@ -0,0 +1,48 @@
+import { createSymbol } from '../helper'
+
+export interface DecoratorFn {
+ (options: T): IsMethod extends false ? PropertyDecorator : MethodDecorator
+ MetadataKey: string | symbol
+}
+export interface MetadataStore {
+ key: string | symbol
+ options: T
+ desc?: PropertyDescriptor | null
+}
+
+export function createDecorator(name: string) {
+ const metaName = `VUE3-OOP_${name.toUpperCase()}`
+ const MetadataKey = createSymbol(metaName)
+ const decoratorFn: DecoratorFn = function (options: T) {
+ return function (target: any, key: string | symbol) {
+ let list: MetadataStore[] = Reflect.getMetadata(MetadataKey, target) || []
+ list = list.slice()
+ const hasItem = list.find((k) => k.key === key)
+ if (!hasItem) list.push({ key, options })
+ else hasItem.options = options
+ Reflect.defineMetadata(MetadataKey, list, target)
+ }
+ }
+ decoratorFn.MetadataKey = MetadataKey
+ Object.defineProperty(decoratorFn, 'MetadataKey', {
+ get() {
+ return MetadataKey
+ },
+ })
+ return decoratorFn
+}
+export function getProtoMetadata(target: any, key: symbol | string, withDesc = false): MetadataStore[] {
+ const proto = Object.getPrototypeOf(target)
+ if (!proto) return []
+ const res: MetadataStore[] = Reflect.getMetadata(key, proto) || []
+ if (withDesc) {
+ res.forEach((k) => (k.desc = getDeepOwnDescriptor(proto, k.key)))
+ }
+ return res
+}
+export function getDeepOwnDescriptor(proto: any, key: string | symbol): PropertyDescriptor | null {
+ if (!proto) return null
+ const desc = Object.getOwnPropertyDescriptor(proto, key)
+ if (desc) return desc
+ return getDeepOwnDescriptor(Object.getPrototypeOf(proto), key)
+}
diff --git a/src/di/index.ts b/src/di/index.ts
index 9f028f3..679a20b 100644
--- a/src/di/index.ts
+++ b/src/di/index.ts
@@ -8,9 +8,11 @@ import {
TypeProvider,
} from 'injection-js'
import { getCurrentInstance, inject, InjectionKey, provide } from 'vue'
+import { createSymbol } from '../helper'
-export const InjectorKey: InjectionKey = Symbol('ReflectiveInjector')
-const MetadataKey = Symbol('Component')
+export const InjectorKey: InjectionKey = createSymbol('VUE3-OOP_ReflectiveInjector') as symbol
+
+const MetadataKey = createSymbol('VUE3-OOP_Component')
declare module 'vue' {
interface App {
@@ -67,6 +69,7 @@ export function resolveComponent(target: { new (...args: []): any }) {
const injector = ReflectiveInjector.fromResolvedProviders(resolveProviders, parent)
if (options?.globalStore) {
// 如果作为全局的服务,则注入到根上面
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const current = getCurrentInstance()!
const app = current.appContext.app
diff --git a/src/extends/component.ts b/src/extends/component.ts
index 9d49eef..7c78ae1 100644
--- a/src/extends/component.ts
+++ b/src/extends/component.ts
@@ -31,28 +31,10 @@ export abstract class VueComponent {
/** 装饰器处理 */
static handler: Hanlder[] = [MutHandler, ComputedHandler, LinkHandler, HookHandler]
/** 是否自定义解析组件 */
- private static resolveComponent = resolveComponent
+ static resolveComponent = resolveComponent
private static __vccOpts__value?: ComponentOptions
/** 组件option定义,vue3遇到类组件会从此属性获取组件的option */
- static get __vccOpts(): ComponentOptions {
- if (this.__vccOpts__value) return this.__vccOpts__value
- const CompConstructor = this as unknown as VueComponentStaticContructor
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- const { displayName, defaultProps, emits, ProviderKey, globalStore, ...left } = CompConstructor
-
- return (this.__vccOpts__value = {
- ...left,
- name: displayName || CompConstructor.name,
- props: defaultProps || {},
- // 放到emits的on函数会自动缓存
- emits: (emits || []).concat(getEmitsFromProps(CompConstructor.defaultProps || {})),
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- setup: (props: any, ctx: any) => {
- const instance = VueComponent.resolveComponent(CompConstructor)
- return instance.render.bind(instance)
- },
- })
- }
+ static __vccOpts: ComponentOptions
/** 是否作为全局store提供外部入口,此时会在 当前app上注入2个方法,用于获取此组件的服务 */
static globalStore?: boolean
/** 是否把自己当做服务provide出去,以便子组件可注入 */
@@ -93,3 +75,27 @@ export abstract class VueComponent {
/** 渲染函数 */
abstract render(ctx: ComponentPublicInstance, cache: any[]): VNodeChild
}
+
+Object.defineProperty(VueComponent, '__vccOpts', {
+ enumerable: true,
+ configurable: true,
+ get() {
+ if (this.__vccOpts__value) return this.__vccOpts__value
+ const CompConstructor = this as unknown as VueComponentStaticContructor
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { displayName, defaultProps, emits, ProviderKey, globalStore, ...left } = CompConstructor
+
+ return (this.__vccOpts__value = {
+ ...left,
+ name: displayName || CompConstructor.name,
+ props: defaultProps || {},
+ // 放到emits的on函数会自动缓存
+ emits: (emits || []).concat(getEmitsFromProps(CompConstructor.defaultProps || {})),
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ setup: (props: any, ctx: any) => {
+ const instance = VueComponent.resolveComponent(CompConstructor)
+ return instance.render.bind(instance)
+ },
+ })
+ },
+})
diff --git a/src/helper.ts b/src/helper.ts
index 4772f65..75ca443 100644
--- a/src/helper.ts
+++ b/src/helper.ts
@@ -3,9 +3,6 @@ import autobind from 'autobind-decorator'
/**
* 自动绑定this !!!此装饰器必须放在最上面
- * @example
- * \@Autobind()
- * \@Abc()
*/
export function Autobind() {
return autobind
@@ -23,35 +20,6 @@ export function useCtx(): SetupContext {
export function getCurrentApp() {
return getCurrentInstance()?.appContext.app
}
-export function getProtoMetadata(target: any, key: symbol, returnDesc = false): any[] {
- if (!target) return []
- const proto = Reflect.getPrototypeOf(target)
- if (!proto) return []
- let res: any[] = Reflect.getMetadata(key, proto) || []
- if (returnDesc) {
- res = res.map((k) => {
- if (typeof k === 'string') {
- return {
- key: k,
- desc: getDeepOwnDescriptor(proto, k),
- }
- }
- if (typeof k === 'object') {
- return {
- key: k,
- desc: getDeepOwnDescriptor(proto, k.key),
- }
- }
- })
- }
- return res
-}
-export function getDeepOwnDescriptor(proto: any, key: string): PropertyDescriptor | null {
- if (!proto) return null
- const desc = Reflect.getOwnPropertyDescriptor(proto, key)
- if (desc) return desc
- return getDeepOwnDescriptor(Reflect.getPrototypeOf(proto), key)
-}
export function getEmitsFromProps(defaultProps: Record | string[]) {
const keys = Array.isArray(defaultProps) ? defaultProps : Object.keys(defaultProps)
const emits: string[] = []
@@ -63,6 +31,9 @@ export function getEmitsFromProps(defaultProps: Record | string[])
}
return emits
}
+export function createSymbol(name: string) {
+ return typeof Symbol === 'undefined' ? name : Symbol(name)
+}
/**
* 注入服务
diff --git a/src/index.ts b/src/index.ts
index c5e4703..1284916 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,6 +1,6 @@
export { VueComponent, GlobalStoreKey } from './extends/component'
export { VueService, ProviderKey } from './extends/service'
-export { Ref, Mut } from './decorators/mut'
+export { Mut } from './decorators/mut'
export { Computed } from './decorators/computed'
export { Link } from './decorators/link'
export { Hook } from './decorators/hook'
diff --git a/src/type.ts b/src/type.ts
index 8a2e62b..dfca06c 100644
--- a/src/type.ts
+++ b/src/type.ts
@@ -1,5 +1,4 @@
-import { InjectionKey, Prop, SetupContext, VNodeChild } from 'vue'
-import { ComponentOptions, ComponentPublicInstance } from '@vue/runtime-core'
+import { ComponentOptions, ComponentPublicInstance, InjectionKey, Prop, SetupContext, VNodeChild } from 'vue'
export interface VueComponentStaticContructor {
new (...args: any[]): ComponentPublicInstance
diff --git a/tsconfig.json b/tsconfig.json
index 04e4b25..134166c 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "ES2015",
+ "target": "ESNext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,