From 455739a4127a53b9c7bfc74f89260ebc9fa3405c Mon Sep 17 00:00:00 2001 From: agileago Date: Sun, 19 Dec 2021 10:24:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Ref=E9=87=8D=E5=91=BD=E5=90=8DTrack?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: Ref因与vue的Ref重名,故改名为Track --- README.md | 8 +++---- docs/guide/api.md | 6 ++--- docs/guide/component.md | 6 ++--- docs/guide/di.md | 4 ++-- docs/guide/service.md | 4 ++-- docs/index.md | 2 +- example/count.service.ts | 4 ++-- example/example.tsx | 6 ++--- example/main.tsx | 16 ++++++++++++- example/module/auth/login.view.tsx | 6 ++--- example/module/auth/user.service.ts | 4 ++-- example/size.service.ts | 36 +++++++++++++++++++++++++++++ package.json | 2 ++ pnpm-lock.yaml | 10 ++++++++ src/decorators/{ref.ts => track.ts} | 16 +++++++++---- src/extends/component.ts | 4 ++-- src/extends/service.ts | 4 ++-- src/index.ts | 2 +- 18 files changed, 105 insertions(+), 35 deletions(-) create mode 100644 example/size.service.ts rename src/decorators/{ref.ts => track.ts} (77%) diff --git a/README.md b/README.md index 60e4a78..ae3366b 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,12 @@ pnpm add vue3-oop ### vite配置 -因为esbuild不支持装饰器的metadata属性,所以需要安装 [vite-plugin-ts](https://github.com/CarterLi/vite/tree/main/packages/plugin-vue-jsx#readme) 插件使用原始ts编译 +因为esbuild不支持装饰器的metadata属性,所以需要安装 [rollup-plugin-typescript2](https://github.com/ezolenko/rollup-plugin-typescript2) 插件使用原始ts编译 ### 定义组件 ```typescript jsx -import { Autobind, ComponentProps, Computed, Hook, Link, Ref, VueComponent } from 'vue3-oop' +import { Autobind, ComponentProps, Computed, Hook, Link, Track, VueComponent } from 'vue3-oop' import { Directive, VNodeChild, watch } from 'vue' const focusDirective: Directive = { @@ -78,7 +78,7 @@ class Foo extends VueComponent { } // 组件自身状态 - @Ref() count = 1 + @Track() count = 1 // 计算属性 @Computed() @@ -127,7 +127,7 @@ class Foo extends VueComponent { ```typescript class CountService extends VueService { - @Ref() count = 1 + @Track() count = 1 add() { this.count++ } diff --git a/docs/guide/api.md b/docs/guide/api.md index e37ebc3..aff86db 100644 --- a/docs/guide/api.md +++ b/docs/guide/api.md @@ -12,14 +12,14 @@ # 装饰器 -## Ref +## Track - Type: 属性装饰器 声明变量为响应式 ```tsx class Foo extends VueComponent { - @Ref() count = 1 + @Track() count = 1 } ``` @@ -30,7 +30,7 @@ class Foo extends VueComponent { ```tsx class Foo extends VueComponent { - @Ref() count = 1 + @Track() count = 1 @Computed() get doubleCount() { diff --git a/docs/guide/component.md b/docs/guide/component.md index 9fffe3d..d87c515 100644 --- a/docs/guide/component.md +++ b/docs/guide/component.md @@ -71,12 +71,12 @@ class Foo extends VueComponent { ## 响应式变量 -响应式变量使用装饰器注解一下,主要有2个 `Ref` 和 `Computed`,此时忘记 `.value` 的事情, +响应式变量使用装饰器注解一下,主要有2个 `Track` 和 `Computed`,此时忘记 `.value` 的事情, 就是正常普通的变量定义,加上装饰器就是告诉框架当此变量变化的时候我要刷新视图 ```tsx class Foo extends VueComponent { - @Ref() count = 1 + @Track() count = 1 @Computed() get doubleCount() { @@ -123,7 +123,7 @@ class Foo extends VueComponent { watch(() => this.count, (n, o) => console.log('change', n, o)) } - @Ref() count = 1 + @Track() count = 1 render() { return this.count++}>{this.count} diff --git a/docs/guide/di.md b/docs/guide/di.md index 7f50ce9..b10f8e7 100644 --- a/docs/guide/di.md +++ b/docs/guide/di.md @@ -16,7 +16,7 @@ import { Injectable } from 'injection-js' // 定义服务 加上此装饰器表明我有需要其他服务,如果不需要,可以不加 @Injectable() class CountService extends VueService { - @Ref() count = 1 + @Track() count = 1 add() { this.count++ @@ -46,7 +46,7 @@ import { VueComponent } from './component' import { SkipSelf } from 'injection-js' class CountService extends VueService { - @Ref() count = 1 + @Track() count = 1 add() { this.count++ diff --git a/docs/guide/service.md b/docs/guide/service.md index 93fe45d..fd27db7 100644 --- a/docs/guide/service.md +++ b/docs/guide/service.md @@ -38,8 +38,8 @@ class PositionService extends VueService { onBeforeUnmount(() => window.removeEventListener('mousemove', this.change)) } - @Ref() x = 0 - @Ref() y = 0 + @Track() x = 0 + @Track() y = 0 @Autobind() private change(e: MouseEvent) { diff --git a/docs/index.md b/docs/index.md index 56ba267..51ba376 100644 --- a/docs/index.md +++ b/docs/index.md @@ -39,7 +39,7 @@ class Foo extends VueComponent { } // 组件自身状态 - @Ref() count = 1 + @Track() count = 1 // 计算属性 @Computed() diff --git a/example/count.service.ts b/example/count.service.ts index 7a2885f..3e64b54 100644 --- a/example/count.service.ts +++ b/example/count.service.ts @@ -1,7 +1,7 @@ -import { Autobind, Ref, VueService } from '@/index' +import { Autobind, Track, VueService } from '@/index' export class CountService extends VueService { - @Ref() count = 0 + @Track() count = 1 @Autobind() add() { diff --git a/example/example.tsx b/example/example.tsx index c0b5b20..5544238 100644 --- a/example/example.tsx +++ b/example/example.tsx @@ -1,4 +1,4 @@ -import { Autobind, Ref, VueComponent, VueService } from 'vue3-oop' +import { Autobind, Track, VueComponent, VueService } from 'vue3-oop' import { onBeforeUnmount } from 'vue' class PositionService extends VueService { @@ -8,8 +8,8 @@ class PositionService extends VueService { onBeforeUnmount(() => window.removeEventListener('mousemove', this.change)) } - @Ref() x = 0 - @Ref() y = 0 + @Track() x = 0 + @Track() y = 0 @Autobind() private change(e: MouseEvent) { diff --git a/example/main.tsx b/example/main.tsx index a7ba6f1..fb1e5b1 100644 --- a/example/main.tsx +++ b/example/main.tsx @@ -3,10 +3,11 @@ import { Component, VueComponent } from 'vue3-oop' import { createApp } from 'vue' import './theme/app.css' import { CountService } from './count.service' +import { SizeService } from './size.service' @Component() class Home extends VueComponent { - constructor(private countService: CountService) { + constructor(private countService: CountService, private sizeService: SizeService) { super() } @@ -16,6 +17,19 @@ class Home extends VueComponent {

count: {this.countService.count}

+

+ 矩形大小: 宽度: {this.sizeService.x} 长度: {this.sizeService.y} +

+
) } diff --git a/example/module/auth/login.view.tsx b/example/module/auth/login.view.tsx index 8be5acb..c3edad8 100644 --- a/example/module/auth/login.view.tsx +++ b/example/module/auth/login.view.tsx @@ -1,7 +1,7 @@ import { Component, VueComponent } from '@/index' import { UserService } from './user.service' import { Button, Col, Form, Input, Row } from 'ant-design-vue' -import { Ref } from '@/decorators/ref' +import { Track } from '@/decorators/track' import { CatchLoading } from '../../common/decorators/catch.decorator' import { Autobind } from '@/helper' import { CountService } from '../../count.service' @@ -19,8 +19,8 @@ export default class LoginView extends VueComponent { ) { super() } - @Ref() loading = false - @Ref() model = { + @Track() loading = false + @Track() model = { name: '', pwd: '', } diff --git a/example/module/auth/user.service.ts b/example/module/auth/user.service.ts index d35daa8..a2390e5 100644 --- a/example/module/auth/user.service.ts +++ b/example/module/auth/user.service.ts @@ -1,4 +1,4 @@ -import { Hook, Ref, VueService } from '@/index' +import { Hook, Track, VueService } from '@/index' import { Inject, Injectable } from 'injection-js' import { RouterService } from '../../router/router.service' import { AxiosInstance } from 'axios' @@ -11,7 +11,7 @@ export class UserService extends VueService { this.guardHttp() this.guardRouter() } - @Ref() token = '' + @Track() token = '' private _requestGuard: number diff --git a/example/size.service.ts b/example/size.service.ts new file mode 100644 index 0000000..4c005fc --- /dev/null +++ b/example/size.service.ts @@ -0,0 +1,36 @@ +import { Hook, Track, VueService } from 'vue3-oop' +import { ref, watchEffect } from 'vue' +import { debounce } from 'lodash-es' + +export class SizeService extends VueService { + constructor() { + super() + watchEffect((onInvalidate) => { + const target = this.target.value + target && this.observer.observe(target) + onInvalidate(() => target && this.observer.unobserve(target)) + }) + } + target = ref() + private observer = new ResizeObserver((entries) => { + const entry = entries[0] + if (!entry) { + this.x = 0 + this.y = 0 + } else { + this.debounceSet(entry.target.clientWidth, entry.target.clientHeight) + } + }) + @Track() x = 0 + @Track() y = 0 + + debounceSet = debounce((x: number, y: number) => { + this.x = x + this.y = y + }) + + @Hook('BeforeUnmount') + private unmount() { + this.observer.disconnect() + } +} diff --git a/package.json b/package.json index 033949f..1c380eb 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "@abraham/reflection": "^0.8.0", "@commitlint/cli": "^15.0.0", "@rollup/plugin-typescript": "^8.3.0", + "@types/lodash-es": "^4.17.5", "@types/markdown-it": "^12.2.3", "@types/prettier": "^2.4.2", "@types/swagger-schema-official": "^2.0.22", @@ -73,6 +74,7 @@ "eslint-plugin-prettier": "^4.0.0", "injection-js": "^2.4.0", "lint-staged": "^12.1.2", + "lodash-es": "^4.17.21", "markdown-it-codetabs": "^1.2.0", "npm-run-all": "^4.1.5", "prettier": "^2.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be839cf..82b2e82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,7 @@ specifiers: '@abraham/reflection': ^0.8.0 '@commitlint/cli': ^15.0.0 '@rollup/plugin-typescript': ^8.3.0 + '@types/lodash-es': ^4.17.5 '@types/markdown-it': ^12.2.3 '@types/prettier': ^2.4.2 '@types/swagger-schema-official': ^2.0.22 @@ -23,6 +24,7 @@ specifiers: eslint-plugin-prettier: ^4.0.0 injection-js: ^2.4.0 lint-staged: ^12.1.2 + lodash-es: ^4.17.21 markdown-it-codetabs: ^1.2.0 npm-run-all: ^4.1.5 prettier: ^2.5.1 @@ -42,6 +44,7 @@ devDependencies: '@abraham/reflection': 0.8.0 '@commitlint/cli': 15.0.0 '@rollup/plugin-typescript': 8.3.0_tslib@2.3.1+typescript@4.5.2 + '@types/lodash-es': 4.17.5 '@types/markdown-it': 12.2.3 '@types/prettier': 2.4.2 '@types/swagger-schema-official': 2.0.22 @@ -61,6 +64,7 @@ devDependencies: eslint-plugin-prettier: 4.0.0_90bd2ba582f6d1348d73031482d782e2 injection-js: 2.4.0 lint-staged: 12.1.2 + lodash-es: 4.17.21 markdown-it-codetabs: 1.2.0 npm-run-all: 4.1.5 prettier: 2.5.1 @@ -821,6 +825,12 @@ packages: resolution: {integrity: sha1-/SzS7bqn6qx+fzwXSLUqGRQ4Rsk=, tarball: '@types/linkify-it/download/@types/linkify-it-3.0.2.tgz'} dev: true + /@types/lodash-es/4.17.5: + resolution: {integrity: sha1-HD/dFoSdhK6kOJCxxg2jeftQE1M=, tarball: '@types/lodash-es/download/@types/lodash-es-4.17.5.tgz'} + dependencies: + '@types/lodash': 4.14.178 + dev: true + /@types/lodash/4.14.178: resolution: {integrity: sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==, tarball: '@types/lodash/download/@types/lodash-4.14.178.tgz'} dev: true diff --git a/src/decorators/ref.ts b/src/decorators/track.ts similarity index 77% rename from src/decorators/ref.ts rename to src/decorators/track.ts index 0d55bf9..0f39b27 100644 --- a/src/decorators/ref.ts +++ b/src/decorators/track.ts @@ -2,8 +2,9 @@ import { ref } from 'vue' import { Hanlder } from '../type' import { getProtoMetadata } from '../helper' -const MetadataKey = Symbol('Ref') -export function Ref(): PropertyDecorator { +const MetadataKey = Symbol('Track') + +export function Track(): PropertyDecorator { return function (target: any, key: string | symbol) { let list: (string | symbol)[] = Reflect.getMetadata(MetadataKey, target) || [] list = list.slice() @@ -31,7 +32,14 @@ function handler(targetThis: Record) { } } -export const RefHandler: Hanlder = { - key: 'Ref', +export const TrackHandler: Hanlder = { + key: 'Track', handler, } + +/** + * @deprecated 因与vue的ref冲突,故改名为 Track + */ +export function Ref() { + return Track() +} diff --git a/src/extends/component.ts b/src/extends/component.ts index 823fd80..f8de1fa 100644 --- a/src/extends/component.ts +++ b/src/extends/component.ts @@ -1,7 +1,7 @@ import { ComponentPublicInstance, getCurrentInstance, InjectionKey, provide, VNodeChild, VNodeProps } from 'vue' import { getEmitsFromProps, useCtx, useProps } from '../helper' import { Hanlder, VueComponentStaticContructor, WithSlotTypes, WithVModel, WithVSlots } from '../type' -import { RefHandler } from '../decorators/ref' +import { TrackHandler } from '../decorators/track' import { ComputedHandler } from '../decorators/computed' import { HookHandler } from '../decorators/hook' import { LinkHandler } from '../decorators/link' @@ -19,7 +19,7 @@ export abstract class VueComponent { /** 热更新使用 */ static __hmrId?: string /** 装饰器处理 */ - static handler: Hanlder[] = [RefHandler, ComputedHandler, LinkHandler, HookHandler] + static handler: Hanlder[] = [TrackHandler, ComputedHandler, LinkHandler, HookHandler] /** 是否自定义解析组件 */ static resolveComponent = resolveComponent static __vccOpts__value?: any diff --git a/src/extends/service.ts b/src/extends/service.ts index 51b1ea1..440d2f2 100644 --- a/src/extends/service.ts +++ b/src/extends/service.ts @@ -1,4 +1,4 @@ -import { RefHandler } from '../decorators/ref' +import { TrackHandler } from '../decorators/track' import { ComputedHandler } from '../decorators/computed' import { HookHandler } from '../decorators/hook' import { provide } from 'vue' @@ -8,7 +8,7 @@ import { LinkHandler } from '../decorators/link' export const ProviderKey = 'ProviderKey' as const export abstract class VueService { - static handler: Hanlder[] = [RefHandler, ComputedHandler, LinkHandler, HookHandler] + static handler: Hanlder[] = [TrackHandler, ComputedHandler, LinkHandler, HookHandler] public constructor() { const ThisConstructor = this.constructor as VueComponentStaticContructor if (ThisConstructor.ProviderKey) provide(ThisConstructor.ProviderKey, this) diff --git a/src/index.ts b/src/index.ts index c4ddfab..f8288bc 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 } from './decorators/ref' +export { Ref, Track } from './decorators/track' export { Computed } from './decorators/computed' export { Link } from './decorators/link' export { Hook } from './decorators/hook'