Skip to content

Commit c6c68db

Browse files
committed
文档: 更新文档
1 parent 5cc1ebe commit c6c68db

File tree

5 files changed

+148
-10
lines changed

5 files changed

+148
-10
lines changed

docs/.vitepress/config.js

Lines changed: 0 additions & 6 deletions
This file was deleted.

docs/.vitepress/config.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { UserConfig } from 'vitepress'
2+
3+
const config: UserConfig = {
4+
base: '/vue3-oop/',
5+
title: 'VUE3-OOP',
6+
description: 'vue3 oop是vue3开发进入面向对象阶段',
7+
themeConfig: {
8+
nav: [
9+
{ text: '指南', link: '/guide/', activeMatch: '^/guide/' },
10+
{
11+
text: 'API参考',
12+
link: '/api/',
13+
activeMatch: '^/api/',
14+
},
15+
{
16+
text: 'Github',
17+
link: 'https://github.com/agileago/vue3-oop',
18+
},
19+
],
20+
},
21+
}
22+
23+
export default config

docs/index.md

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,94 @@
1-
# vue3 oop
1+
---
2+
home: true
3+
heroText: VUE3面向对象编程
4+
tagline: 极致优秀的编码体验
5+
actionText: 开始使用
6+
actionLink: /guide/
7+
features:
8+
- title: 类组件
9+
details: 功能与类型融为一体,无需多次声明类型,独立的属性类型声明,各种HOC组合轻而易举
10+
- title: 自动的依赖注入
11+
details: 基于动态解析的 injection-js 依赖注入,让使用服务丝般自然
12+
- title: vue3无ref编程
13+
details: 无需关注ref及其value,正常声明变量,编程体验更自然
14+
---
15+
16+
#### 以下代码展示常用API
17+
18+
```typescript jsx
19+
import { VueComponent, Ref, Autobind, VueService } from "vue3-oop"
20+
import { Injectable } from "injection-js"
21+
import { createApp, VNodeChild } from "vue"
22+
23+
// 服务,即可复用的逻辑 类似 useXXX
24+
@Injectable()
25+
class CountService extends VueService {
26+
@Ref() count = 0
27+
28+
@Autobind()
29+
add() {
30+
this.count++
31+
}
32+
33+
@Autobind()
34+
remove() {
35+
this.count--
36+
}
37+
}
38+
// 组件
39+
@Component({
40+
providers: [CountService]
41+
})
42+
class Home extends VueComponent {
43+
// 构造函数注入服务,无需new
44+
constructor(private countService: CountService) {
45+
super()
46+
}
47+
48+
render() {
49+
return <div>
50+
<span onClick={this.countService.add}>+</span>
51+
{this.countService.count}
52+
<span onClick={this.countService.remove}>-</span>
53+
</div>
54+
}
55+
}
56+
57+
// 子组件属性
58+
interface HomeChild_Props<DataItem = any> {
59+
list: DataItem[]
60+
title: string | ((list: DataItem[]) => VNodeChild)
61+
['v-slots']?: {
62+
default(): VNodeChild
63+
item(item: DataItem): VNodeChild
64+
}
65+
}
66+
67+
// 子组件
68+
class HomeChild<T> extends VueComponent<HomeChild_Props<T>> {
69+
static defaultProps: ComponentProps<HomeChild_Props> = {
70+
list: {
71+
type: Array,
72+
required: true
73+
},
74+
title: {
75+
type: [String, Function],
76+
required: true
77+
},
78+
}
79+
80+
render() {
81+
return (
82+
<div>
83+
{
84+
85+
}
86+
</div>
87+
);
88+
}
89+
90+
}
91+
92+
const app = createApp(Home)
93+
app.mount('#app')
94+
```

example/module/auth/login.view.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CatchLoading } from '../../common/decorators/catch.decorator'
66
import { Autobind } from '@/helper'
77
import { CountService } from '../../count.service'
88
import { SkipSelf } from 'injection-js'
9+
import { VNodeChild } from 'vue'
910

1011
@Component({
1112
providers: [CountService],
@@ -35,6 +36,12 @@ export default class LoginView extends VueComponent {
3536
}
3637

3738
render() {
39+
const hslots: HomeChild<any>['props']['v-slots'] = {
40+
$stable: true,
41+
item(): VNodeChild {
42+
return <div>111</div>
43+
},
44+
}
3845
return (
3946
<Row type={'flex'} justify={'center'} align={'middle'} style={{ height: '80%' }}>
4047
<Col span={12}>
@@ -65,8 +72,24 @@ export default class LoginView extends VueComponent {
6572
</Button>
6673
</Form.Item>
6774
</Form>
75+
<HomeChild v-slots={hslots}></HomeChild>
6876
</Col>
6977
</Row>
7078
)
7179
}
7280
}
81+
interface HomeChild_Props<DataItem = any> {
82+
list?: DataItem[]
83+
title?: string | ((list: DataItem[]) => VNodeChild)
84+
/**
85+
* 插槽
86+
*/
87+
slots?: {
88+
item(): VNodeChild
89+
}
90+
}
91+
class HomeChild<T> extends VueComponent<HomeChild_Props<T>> {
92+
render() {
93+
return <div></div>
94+
}
95+
}

src/extends/component.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import { LinkHandler } from '@/decorators/link'
88

99
export const GlobalStoreKey = 'GlobalStoreKey'
1010

11+
// 处理tsx slots 类型问题
12+
type WithVSlots<T extends Record<string, any>> = 'slots' extends keyof T
13+
? { 'v-slots'?: T['slots'] & { $stable?: boolean } }
14+
: Record<string, never>
15+
1116
export abstract class VueComponent<T = Record<string, any>> {
1217
/** 装饰器处理 */
1318
static handler: Hanlder[] = [RefHandler, ComputedHandler, LinkHandler, HookHandler]
@@ -47,12 +52,12 @@ export abstract class VueComponent<T = Record<string, any>> {
4752
return this.props
4853
}
4954
/** 组件属性 */
50-
public props: T & VNodeProps & Record<string, any>
55+
public props: Omit<T, 'slots'> & WithVSlots<T> & VNodeProps & Record<string, any>
5156
/** 组件上下文 */
5257
public context: SetupContext
5358

5459
constructor() {
55-
this.props = useProps<T & VNodeProps>()
60+
this.props = useProps<Omit<T, 'slots'> & VNodeProps & WithVSlots<T>>()
5661
this.context = useCtx()
5762
this.context.expose(this)
5863
const ThisConstructor = this.constructor as VueComponentStaticContructor
@@ -81,5 +86,5 @@ export abstract class VueComponent<T = Record<string, any>> {
8186
}
8287

8388
export type ComponentProps<T extends Record<string, any>> = {
84-
[U in keyof T]-?: Prop<any>
89+
[U in keyof Omit<T, 'slots'>]-?: Prop<any>
8590
}

0 commit comments

Comments
 (0)