Skip to content

Commit

Permalink
feat: 增加类型帮助函数
Browse files Browse the repository at this point in the history
  • Loading branch information
agileago committed Dec 5, 2021
1 parent 6a66603 commit 07ef3a6
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 16 deletions.
26 changes: 23 additions & 3 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,35 @@ const config: UserConfig = {
nav: [
{ text: '指南', link: '/guide/', activeMatch: '^/guide/' },
{
text: 'API参考',
link: '/api/',
activeMatch: '^/api/',
text: 'DEMO',
link: 'https://stackblitz.com/edit/vite-y7m4fy?file=main.tsx',
},
{
text: 'Github',
link: 'https://github.com/agileago/vue3-oop',
},
],
sidebar: {
'/guide/': [
{
text: '介绍',
children: [
{ text: '使用指南', link: '/guide/' },
{ text: '组件', link: '/guide/component' },
{ text: '服务', link: '/guide/service' },
{ text: '装饰器', link: '/guide/decorators' },
],
},
{
text: '依赖注入',
children: [{ text: '服务注入', link: '/guide/di' }],
},
{
text: '类型',
children: [{ text: '类型帮助', link: '/guide/type' }],
},
],
},
},
}

Expand Down
1 change: 1 addition & 0 deletions docs/guide/component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#
49 changes: 49 additions & 0 deletions docs/guide/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# 如何使用

## 前提条件

1. 因为要用到ts的获取元数据的能力,所以需要安装`reflect-metada`的支持

```shell
yarn add @abraham/reflection
```
并且把这段代码放到入口引入,只需引入一次

```typescript
import '@abraham/reflection'
```

2. 安装依赖注入库 `injection-js`, 以及本库

```shell
yarn add injection-js vue3-oop
```

3. 设置 `tsconfig.json`

主要是涉及到装饰器以及类的设置

```json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"useDefineForClassFields": false,
}
}
```

4. 如果使用 `vite` 的话,由于vite使用`esbuild`编译`ts`,不支持 `metadata` , 需要把 `@vitejs/plugin-vue-jsx` 这个插件换成`vite-plugin-ts`这个插件

```shell
yarn add vite-plugin-ts
```

vite 插件配置
```typescript
import vueJsx from 'vite-plugin-ts'
export default {
plugins: [vueJsx()]
}
```

5 changes: 1 addition & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,4 @@ features:
details: 基于动态解析的 injection-js 依赖注入,让使用服务丝般自然
- title: vue3无ref编程
details: 无需关注ref及其value,正常声明变量,编程体验更自然
---


<iframe src="https://stackblitz.com/edit/vite-y7m4fy?embed=1&file=main.tsx" height="600" width="100%" frameborder="0"></iframe>
---
29 changes: 22 additions & 7 deletions example/main.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import '@abraham/reflection'
import type { ClassType } from '@/index'
import { Autobind, Component, ComponentProps, Computed, Hook, Link, Ref, VueComponent, VueService } from '@/index'
import { forwardRef, Inject, Injectable, SkipSelf } from 'injection-js'
import { createApp, watch } from 'vue'
import { createApp, VNodeChild, watch } from 'vue'

// 服务,即可复用的逻辑 类似 useXXX
@Injectable()
Expand All @@ -22,6 +23,10 @@ class CountService extends VueService {
// 组件属性声明
interface HomeChild_Props {
size: 'small' | 'large'
// 组件个性化定义属性
slots: {
item(name: string): VNodeChild
}
}

// 带属性组件
Expand All @@ -34,7 +39,7 @@ class HomeChild extends VueComponent<HomeChild_Props> {
constructor(
private countService: CountService,
@SkipSelf() private parentCountService: CountService,
@Inject(forwardRef(() => Home)) private parent: InstanceType<typeof Home>,
@Inject(forwardRef(() => Home)) private parent: ClassType<Home>,
) {
super()
}
Expand All @@ -50,12 +55,16 @@ class HomeChild extends VueComponent<HomeChild_Props> {
<button onClick={this.countService.add}>+</button>
{this.countService.count}
<button onClick={this.countService.remove}>-</button>
<div>
<h3>这里是组件定制化内容</h3>
{this.context.slots.item?.('我是定制化内容')}
</div>
</div>
)
}
}

// 组件
@Autobind() // 绑定this 也可以放到这里
@Component({ providers: [CountService] }) // 声明自己的服务
class Home extends VueComponent {
// 构造函数注入服务,无需new
Expand Down Expand Up @@ -83,14 +92,12 @@ class Home extends VueComponent {
}

// 子组件引用 链接🔗
@Link() child?: HomeChild
@Link() child?: ClassType<HomeChild>

@Autobind()
add() {
this.count++
}

@Autobind()
remove() {
this.count--
}
Expand All @@ -108,7 +115,15 @@ class Home extends VueComponent {
{this.count}
<button onClick={this.remove}>-</button>

<HomeChild ref="child" size={'small'}></HomeChild>
<HomeChild
ref="child"
size={'small'}
v-slots={{
item(name: string) {
return <span>{name}</span>
},
}}
></HomeChild>
</div>
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/di/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function Component(options?: ComponentOptions): ClassDecorator {
export function resolveComponent(target: { new (...args: []): any }) {
// 如果没有使用 injection-js 则不创建注入器
if (!Reflect.getMetadata('annotations', target)) return new target()
const parent = inject(InjectorKey)
const parent = inject(InjectorKey, undefined)
const options: ComponentOptions | undefined = Reflect.getOwnMetadata(MetadataKey, target)
// 自动解析依赖,根据组件
let deps: Provider[] = options?.autoResolveDeps ? resolveDependencies(target) : options?.providers || []
Expand Down
3 changes: 3 additions & 0 deletions src/extends/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,6 @@ export type ComponentSlots<T extends { props: any }> = T extends { props: infer
? U['v-slots']
: Record<string, unknown>
: never

/** 为了阻止ts把不相关的类也解析到metadata数据中,用这个工具类型包装一下类 */
export type ClassType<T extends Record<string, any>> = T
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ export { Hook } from './decorators/hook'
export * from './helper'
export { Component, InjectorKey } from './di'
export type { ComponentOptions } from './di'
export type { ComponentProps, ComponentSlots } from './extends/component'
export type { ComponentProps, ComponentSlots, ClassType } from './extends/component'

0 comments on commit 07ef3a6

Please sign in to comment.