Skip to content

Commit 22d2c31

Browse files
committed
feat: 增加app获取
1 parent 60f094f commit 22d2c31

20 files changed

+226
-140
lines changed

docs/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# Hello VitePress
1+
# vue3 oop

example/api/http.ts

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
11
import axios from 'axios'
2-
import type { App } from 'vue'
3-
import { UserService } from '../module/auth/user.service'
42

53
export const http = axios.create()
6-
let app: App | undefined = undefined
7-
export function setupHttp(obj: App) {
8-
app = obj
9-
}
10-
11-
http.interceptors.request.use((config) => {
12-
const userService = app?.getService(UserService)
13-
console.log(userService)
14-
return config
15-
})
4+
export const HTTP_CLIENT = Symbol()
165

176
export function login() {
187
return http.get('/login')

example/app.tsx

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Component } from '@/di'
2+
import { VueComponent } from '@/index'
3+
import { UserService } from './module/auth/user.service'
4+
import { Button, Col, ConfigProvider, Row } from 'ant-design-vue'
5+
import zhCN from 'ant-design-vue/es/locale/zh_CN'
6+
import { RouterView } from 'vue-router'
7+
import { RouterService } from './router/router.service'
8+
import { http, HTTP_CLIENT } from './api/http'
9+
import { CountService } from './count.service'
10+
11+
@Component({
12+
providers: [UserService, RouterService, { provide: HTTP_CLIENT, useValue: http }, CountService],
13+
})
14+
export class App extends VueComponent {
15+
constructor(
16+
private userService: UserService,
17+
private routerService: RouterService,
18+
private countService: CountService,
19+
) {
20+
super()
21+
}
22+
render() {
23+
return (
24+
<ConfigProvider locale={zhCN}>
25+
<h2 style={{ textAlign: 'center' }}>全局服务</h2>
26+
<Row justify={'center'}>
27+
<Col>
28+
<Button type={'primary'} onClick={this.countService.add}>
29+
30+
</Button>
31+
<span style={{ fontSize: '24px', margin: '0 20px' }}>{this.countService.count}</span>
32+
<Button type={'primary'} danger onClick={this.countService.remove}>
33+
34+
</Button>
35+
</Col>
36+
</Row>
37+
<RouterView></RouterView>
38+
</ConfigProvider>
39+
)
40+
}
41+
}

example/count.service.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Autobind, Ref, VueService } from '@/index'
2+
3+
export class CountService extends VueService {
4+
@Ref() count = 0
5+
6+
@Autobind()
7+
add() {
8+
this.count++
9+
}
10+
11+
@Autobind()
12+
remove() {
13+
this.count--
14+
}
15+
}

example/layout/default.layout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { VueComponent } from '@/extends/component'
1+
import { VueComponent } from '@/index'
22
import { RouterView } from 'vue-router'
33

44
export default class DefaultLayout extends VueComponent {

example/main.tsx

+1-25
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,8 @@
11
import '@abraham/reflection'
22
import { createApp } from 'vue'
3-
import { VueComponent } from '@/extends/component'
4-
import { RouterView } from 'vue-router'
5-
import { setupRouter } from './router'
6-
import { Component } from '@/di'
7-
import { UserService } from './module/auth/user.service'
83
import './theme/app.css'
94
import 'ant-design-vue/dist/antd.css'
10-
import { Button, ConfigProvider, Table } from 'ant-design-vue'
11-
import zhCN from 'ant-design-vue/es/locale/zh_CN'
12-
import { setupHttp } from './api/http'
13-
14-
@Component({ autoResolveDeps: true, globalStore: true })
15-
class App extends VueComponent {
16-
constructor(private userService: UserService) {
17-
super()
18-
}
19-
render() {
20-
return (
21-
<ConfigProvider locale={zhCN}>
22-
<h2 style={{ textAlign: 'center' }}>全局服务</h2>
23-
<RouterView></RouterView>
24-
</ConfigProvider>
25-
)
26-
}
27-
}
5+
import { App } from './app'
286

297
const app = createApp(App)
30-
setupRouter(app)
31-
setupHttp(app)
328
app.mount('#app')

example/module/auth/login.view.tsx

+25-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
import { VueComponent } from '@/extends/component'
2-
import { Component } from '@/di'
1+
import { Component, VueComponent } from '@/index'
32
import { UserService } from './user.service'
43
import { Button, Col, Form, Input, Row } from 'ant-design-vue'
54
import { Ref } from '@/decorators/ref'
65
import { CatchLoading } from '../../common/decorators/catch.decorator'
76
import { Autobind } from '@/helper'
7+
import { CountService } from '../../count.service'
8+
import { SkipSelf } from 'injection-js'
89

9-
@Component()
10+
@Component({
11+
providers: [CountService],
12+
})
1013
export default class LoginView extends VueComponent {
11-
constructor(private userService: UserService) {
14+
constructor(
15+
private userService: UserService,
16+
@SkipSelf() private parentCountService: CountService,
17+
private countService: CountService,
18+
) {
1219
super()
1320
}
1421
@Ref() loading = false
@@ -31,6 +38,20 @@ export default class LoginView extends VueComponent {
3138
return (
3239
<Row type={'flex'} justify={'center'} align={'middle'} style={{ height: '80%' }}>
3340
<Col span={12}>
41+
<h3 style={{ textAlign: 'center' }}>全局的状态: {this.parentCountService.count}</h3>
42+
<h3 style={{ textAlign: 'center' }}>局部的状态</h3>
43+
<Row justify={'center'}>
44+
<Col>
45+
<Button type={'primary'} onClick={this.countService.add}>
46+
47+
</Button>
48+
<span style={{ fontSize: '24px', margin: '0 20px' }}>{this.countService.count}</span>
49+
<Button type={'primary'} danger onClick={this.countService.remove}>
50+
51+
</Button>
52+
</Col>
53+
</Row>
54+
<br />
3455
<Form labelCol={{ span: 6 }} model={this.model} rules={this.rules} onFinish={this.submit}>
3556
<Form.Item label={'用户名'} name={'name'}>
3657
<Input v-model={[this.model.name, 'value']}></Input>

example/module/auth/user.service.ts

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
1-
import { VueService } from '@/extends/service'
2-
import { Injectable } from 'injection-js'
1+
import { Hook, Ref, VueService } from '@/index'
2+
import { Inject, Injectable } from 'injection-js'
33
import { RouterService } from '../../router/router.service'
4-
import { Ref } from '@/index'
4+
import { AxiosInstance } from 'axios'
5+
import { HTTP_CLIENT } from '../../api/http'
56

67
@Injectable()
78
export class UserService extends VueService {
8-
constructor(private routerService: RouterService) {
9+
constructor(private routerService: RouterService, @Inject(HTTP_CLIENT) private httpService: AxiosInstance) {
910
super()
11+
this.guardHttp()
1012
this.guardRouter()
1113
}
12-
@Ref() token?: string
14+
@Ref() token = ''
15+
16+
private _requestGuard: number
17+
18+
guardHttp() {
19+
this._requestGuard = this.httpService.interceptors.request.use((config) => {
20+
return config
21+
})
22+
}
1323

1424
guardRouter() {
1525
this.routerService.router.beforeEach(async (to, from) => {
1626
if (to.path === '/login' && this.token) return { path: '/' }
1727
if (to.path !== '/login' && !this.token) return { path: '/login' }
1828
})
1929
}
30+
31+
@Hook('BeforeUnmount')
32+
unmount() {
33+
this.httpService.interceptors.request.eject(this._requestGuard)
34+
}
35+
2036
async login(model: any) {
21-
this.token = await new Promise((resolve) => setTimeout(resolve, 3000, 'token'))
22-
this.routerService.router.replace('/')
37+
this.token = await new Promise((resolve) => setTimeout(resolve, 1000, 'token'))
38+
await this.routerService.router.replace('/')
2339
}
2440
}

example/module/home/home.view.tsx

+39-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,44 @@
1-
import { VueComponent } from '@/extends/component'
1+
import { Component, VueComponent } from '@/index'
2+
import { CountService } from '../../count.service'
3+
import { Optional, SkipSelf } from 'injection-js'
4+
import { Button, Col, Row } from 'ant-design-vue'
5+
import { watch } from 'vue'
26

7+
@Component({
8+
providers: [CountService],
9+
})
310
export default class HomeView extends VueComponent {
11+
constructor(
12+
@SkipSelf() private parentCountService: CountService,
13+
private countService: CountService,
14+
@Optional() private aaa: string,
15+
) {
16+
super()
17+
watch(
18+
() => this.parentCountService.count,
19+
() => (countService.count = parentCountService.count),
20+
{
21+
immediate: true,
22+
},
23+
)
24+
}
425
render() {
5-
return <div>home</div>
26+
return (
27+
<>
28+
<h3 style={{ textAlign: 'center' }}>全局的状态: {this.parentCountService.count}</h3>
29+
<h3 style={{ textAlign: 'center' }}>局部的状态</h3>
30+
<Row justify={'center'}>
31+
<Col>
32+
<Button type={'primary'} onClick={this.countService.add}>
33+
34+
</Button>
35+
<span style={{ fontSize: '24px', margin: '0 20px' }}>{this.countService.count}</span>
36+
<Button type={'primary'} danger onClick={this.countService.remove}>
37+
38+
</Button>
39+
</Col>
40+
</Row>
41+
</>
42+
)
643
}
744
}

example/router/index.ts

-11
This file was deleted.

example/router/router.service.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
import { Injectable } from 'injection-js'
2-
import { useRouter } from 'vue-router'
2+
import { createRouter, createWebHistory } from 'vue-router'
3+
import { routes } from './routes'
4+
import { getCurrentApp, VueService } from '@/index'
35

46
@Injectable()
5-
export class RouterService {
6-
router = useRouter()
7+
export class RouterService extends VueService {
8+
history = createWebHistory()
9+
router = createRouter({
10+
history: this.history,
11+
routes: routes,
12+
})
13+
app = getCurrentApp()!
14+
get currentRoute() {
15+
return this.router.currentRoute.value
16+
}
17+
18+
constructor() {
19+
super()
20+
this.app.use(this.router)
21+
}
722
}

src/decorators/computed.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface ComputedItem {
88
}
99

1010
const MetadataKey = Symbol('Computed')
11-
export function Computed() {
11+
export function Computed(): MethodDecorator {
1212
return function (target: any, key: string | symbol) {
1313
let list: (string | symbol)[] = Reflect.getMetadata(MetadataKey, target) || []
1414
list = list.slice()

src/decorators/hook.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ type Lifecycle =
3636

3737
const MetadataKey = Symbol('Hook')
3838

39-
export function Hook(lifecycle: Lifecycle) {
39+
export function Hook(lifecycle: Lifecycle): MethodDecorator {
4040
return function (target: any, key: string | symbol) {
4141
let list: HookItem[] = Reflect.getMetadata(MetadataKey, target) || []
4242
list = list.slice()

src/decorators/ref.ts

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ const MetadataKey = Symbol('Ref')
66
export function Ref(): PropertyDecorator {
77
return function (target: any, key: string | symbol) {
88
let list: (string | symbol)[] = Reflect.getMetadata(MetadataKey, target) || []
9-
// 处理原型链上的数据
109
list = list.slice()
1110
const hasItem = list.find((k) => k === key)
1211
if (!hasItem) list.push(key)

src/di/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ const MetadataKey = Symbol('Component')
66

77
declare module 'vue' {
88
interface App {
9-
getStore(): ReflectiveInjector
10-
getService: ReflectiveInjector['get']
9+
getStore(): any
10+
getService(token: any): any
1111
}
1212
}
1313

@@ -30,7 +30,7 @@ export interface ComponentOptions {
3030
globalStore?: boolean
3131
}
3232

33-
export function Component(options?: ComponentOptions) {
33+
export function Component(options?: ComponentOptions): ClassDecorator {
3434
return function (target: any) {
3535
if (!target.resolveComponent) target.resolveComponent = resolveComponent
3636
Reflect.defineMetadata(MetadataKey, options, target)

0 commit comments

Comments
 (0)