Skip to content

Commit

Permalink
feat: 增加app获取
Browse files Browse the repository at this point in the history
  • Loading branch information
agileago committed Dec 4, 2021
1 parent 60f094f commit 22d2c31
Show file tree
Hide file tree
Showing 20 changed files with 226 additions and 140 deletions.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# Hello VitePress
# vue3 oop
13 changes: 1 addition & 12 deletions example/api/http.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
import axios from 'axios'
import type { App } from 'vue'
import { UserService } from '../module/auth/user.service'

export const http = axios.create()
let app: App | undefined = undefined
export function setupHttp(obj: App) {
app = obj
}

http.interceptors.request.use((config) => {
const userService = app?.getService(UserService)
console.log(userService)
return config
})
export const HTTP_CLIENT = Symbol()

export function login() {
return http.get('/login')
Expand Down
41 changes: 41 additions & 0 deletions example/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Component } from '@/di'
import { VueComponent } from '@/index'
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 (
<ConfigProvider locale={zhCN}>
<h2 style={{ textAlign: 'center' }}>全局服务</h2>
<Row justify={'center'}>
<Col>
<Button type={'primary'} onClick={this.countService.add}>
</Button>
<span style={{ fontSize: '24px', margin: '0 20px' }}>{this.countService.count}</span>
<Button type={'primary'} danger onClick={this.countService.remove}>
</Button>
</Col>
</Row>
<RouterView></RouterView>
</ConfigProvider>
)
}
}
15 changes: 15 additions & 0 deletions example/count.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Autobind, Ref, VueService } from '@/index'

export class CountService extends VueService {
@Ref() count = 0

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

@Autobind()
remove() {
this.count--
}
}
2 changes: 1 addition & 1 deletion example/layout/default.layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { VueComponent } from '@/extends/component'
import { VueComponent } from '@/index'
import { RouterView } from 'vue-router'

export default class DefaultLayout extends VueComponent {
Expand Down
26 changes: 1 addition & 25 deletions example/main.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,8 @@
import '@abraham/reflection'
import { createApp } from 'vue'
import { VueComponent } from '@/extends/component'
import { RouterView } from 'vue-router'
import { setupRouter } from './router'
import { Component } from '@/di'
import { UserService } from './module/auth/user.service'
import './theme/app.css'
import 'ant-design-vue/dist/antd.css'
import { Button, ConfigProvider, Table } from 'ant-design-vue'
import zhCN from 'ant-design-vue/es/locale/zh_CN'
import { setupHttp } from './api/http'

@Component({ autoResolveDeps: true, globalStore: true })
class App extends VueComponent {
constructor(private userService: UserService) {
super()
}
render() {
return (
<ConfigProvider locale={zhCN}>
<h2 style={{ textAlign: 'center' }}>全局服务</h2>
<RouterView></RouterView>
</ConfigProvider>
)
}
}
import { App } from './app'

const app = createApp(App)
setupRouter(app)
setupHttp(app)
app.mount('#app')
29 changes: 25 additions & 4 deletions example/module/auth/login.view.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { VueComponent } from '@/extends/component'
import { Component } from '@/di'
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 { CatchLoading } from '../../common/decorators/catch.decorator'
import { Autobind } from '@/helper'
import { CountService } from '../../count.service'
import { SkipSelf } from 'injection-js'

@Component()
@Component({
providers: [CountService],
})
export default class LoginView extends VueComponent {
constructor(private userService: UserService) {
constructor(
private userService: UserService,
@SkipSelf() private parentCountService: CountService,
private countService: CountService,
) {
super()
}
@Ref() loading = false
Expand All @@ -31,6 +38,20 @@ export default class LoginView extends VueComponent {
return (
<Row type={'flex'} justify={'center'} align={'middle'} style={{ height: '80%' }}>
<Col span={12}>
<h3 style={{ textAlign: 'center' }}>全局的状态: {this.parentCountService.count}</h3>
<h3 style={{ textAlign: 'center' }}>局部的状态</h3>
<Row justify={'center'}>
<Col>
<Button type={'primary'} onClick={this.countService.add}>
</Button>
<span style={{ fontSize: '24px', margin: '0 20px' }}>{this.countService.count}</span>
<Button type={'primary'} danger onClick={this.countService.remove}>
</Button>
</Col>
</Row>
<br />
<Form labelCol={{ span: 6 }} model={this.model} rules={this.rules} onFinish={this.submit}>
<Form.Item label={'用户名'} name={'name'}>
<Input v-model={[this.model.name, 'value']}></Input>
Expand Down
30 changes: 23 additions & 7 deletions example/module/auth/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
import { VueService } from '@/extends/service'
import { Injectable } from 'injection-js'
import { Hook, Ref, VueService } from '@/index'
import { Inject, Injectable } from 'injection-js'
import { RouterService } from '../../router/router.service'
import { Ref } from '@/index'
import { AxiosInstance } from 'axios'
import { HTTP_CLIENT } from '../../api/http'

@Injectable()
export class UserService extends VueService {
constructor(private routerService: RouterService) {
constructor(private routerService: RouterService, @Inject(HTTP_CLIENT) private httpService: AxiosInstance) {
super()
this.guardHttp()
this.guardRouter()
}
@Ref() token?: string
@Ref() 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, 3000, 'token'))
this.routerService.router.replace('/')
this.token = await new Promise((resolve) => setTimeout(resolve, 1000, 'token'))
await this.routerService.router.replace('/')
}
}
41 changes: 39 additions & 2 deletions example/module/home/home.view.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,44 @@
import { VueComponent } from '@/extends/component'
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'

@Component({
providers: [CountService],
})
export default class HomeView extends VueComponent {
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 <div>home</div>
return (
<>
<h3 style={{ textAlign: 'center' }}>全局的状态: {this.parentCountService.count}</h3>
<h3 style={{ textAlign: 'center' }}>局部的状态</h3>
<Row justify={'center'}>
<Col>
<Button type={'primary'} onClick={this.countService.add}>
</Button>
<span style={{ fontSize: '24px', margin: '0 20px' }}>{this.countService.count}</span>
<Button type={'primary'} danger onClick={this.countService.remove}>
</Button>
</Col>
</Row>
</>
)
}
}
11 changes: 0 additions & 11 deletions example/router/index.ts

This file was deleted.

21 changes: 18 additions & 3 deletions example/router/router.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
import { Injectable } from 'injection-js'
import { useRouter } from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import { routes } from './routes'
import { getCurrentApp, VueService } from '@/index'

@Injectable()
export class RouterService {
router = useRouter()
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)
}
}
2 changes: 1 addition & 1 deletion src/decorators/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface ComputedItem {
}

const MetadataKey = Symbol('Computed')
export function Computed() {
export function Computed(): MethodDecorator {
return function (target: any, key: string | symbol) {
let list: (string | symbol)[] = Reflect.getMetadata(MetadataKey, target) || []
list = list.slice()
Expand Down
2 changes: 1 addition & 1 deletion src/decorators/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type Lifecycle =

const MetadataKey = Symbol('Hook')

export function Hook(lifecycle: Lifecycle) {
export function Hook(lifecycle: Lifecycle): MethodDecorator {
return function (target: any, key: string | symbol) {
let list: HookItem[] = Reflect.getMetadata(MetadataKey, target) || []
list = list.slice()
Expand Down
1 change: 0 additions & 1 deletion src/decorators/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const MetadataKey = Symbol('Ref')
export function Ref(): 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)
Expand Down
6 changes: 3 additions & 3 deletions src/di/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const MetadataKey = Symbol('Component')

declare module 'vue' {
interface App {
getStore(): ReflectiveInjector
getService: ReflectiveInjector['get']
getStore(): any
getService(token: any): any
}
}

Expand All @@ -30,7 +30,7 @@ export interface ComponentOptions {
globalStore?: boolean
}

export function Component(options?: ComponentOptions) {
export function Component(options?: ComponentOptions): ClassDecorator {
return function (target: any) {
if (!target.resolveComponent) target.resolveComponent = resolveComponent
Reflect.defineMetadata(MetadataKey, options, target)
Expand Down
Loading

0 comments on commit 22d2c31

Please sign in to comment.