Skip to content

Commit 9076d9c

Browse files
committed
feat: 支持模板
1 parent a6e206d commit 9076d9c

File tree

9 files changed

+81
-7
lines changed

9 files changed

+81
-7
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ coverage
1111
commitlint.config.js
1212
.cz-config.js
1313
.prettierrc.js
14+
*.vue

example/main.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import '@abraham/reflection'
2-
import { Component, Mut, VueComponent } from 'vue3-oop'
2+
import { createCurrentInjector, Mut, VueComponent } from 'vue3-oop'
33
import { createApp } from 'vue'
44
import 'ant-design-vue/dist/antd.css'
55
import { Layout, Menu } from 'ant-design-vue'
66
import { RouterLink, RouterView } from 'vue-router'
77
import { RouterStartService } from './router'
88
import { routes } from './router/routes'
99

10-
@Component({ providers: [RouterStartService] })
1110
class App extends VueComponent {
11+
injector = createCurrentInjector([RouterStartService])
1212
@Mut() collapsed = false
1313
render() {
1414
return (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { type ComponentProps, VueComponent } from 'vue3-oop'
2+
3+
interface CountCompProps {
4+
size: 'large' | 'small'
5+
}
6+
7+
export class CountComp extends VueComponent<CountCompProps> {
8+
static defaultProps: ComponentProps<CountCompProps> = ['size']
9+
10+
render() {
11+
return <div>{this.props.size}</div>
12+
}
13+
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<script lang="ts">
2+
import { getCurrentInjector, Mut, VueComponent } from 'vue3-oop'
3+
import { CountComp } from './count.comp'
4+
import { RouterService } from '../../../router/router.service'
5+
6+
export default class Hello extends VueComponent {
7+
static components = {
8+
CountComp,
9+
}
10+
@Mut() count = 1
11+
add = () => this.count++
12+
injector = getCurrentInjector()
13+
router: RouterService = this.injector.get(RouterService)
14+
constructor() {
15+
super()
16+
console.log(this.router)
17+
}
18+
}
19+
</script>
20+
21+
<template>
22+
<h2 class="abc">aaa1111</h2>
23+
<p @click="add">{{ count }}</p>
24+
<CountComp size="large"></CountComp>
25+
</template>
26+
27+
<style lang="scss" scoped>
28+
.abc {
29+
color: red;
30+
}
31+
</style>

example/router/routes.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const routes: RouteRecordRaw[] = [
1212
children: [
1313
{
1414
path: '/basic/hello-world',
15-
component: () => import('../module/basic/hello-world/hello-world.view'),
15+
component: () => import('../module/basic/hello-world/hello.vue'),
1616
meta: {
1717
title: 'Hello Wolrd',
1818
},

src/di/index.ts

+21
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export function resolveComponent(target: { new (...args: []): any }) {
6363
// 如果没有使用 injection-js 则不创建注入器
6464
if (!Reflect.getMetadata('annotations', target)) return new target()
6565
const parent = inject(InjectorKey, undefined)
66+
// 从缓存中拿到解析过得依赖
6667
let resolveProviders = Reflect.getOwnMetadata<ResolvedReflectiveProvider[]>(
6768
MetadataProviderKey,
6869
target
@@ -161,3 +162,23 @@ export function getCurrentInjector(): ReflectiveInjector {
161162
// @ts-ignore
162163
return instance.provides[InjectorKey] || inject(InjectorKey)
163164
}
165+
/** 手动创建当前注射器, 只能用在 setup 中 */
166+
export function createCurrentInjector(
167+
providers: Provider[],
168+
exclude?: Provider[]
169+
): ReflectiveInjector {
170+
let deps = resolveDependencies(providers)
171+
if (exclude?.length) {
172+
deps = deps.filter((k) => exclude?.includes(k))
173+
}
174+
const resolveProviders = ReflectiveInjector.resolve(deps)
175+
const parent = inject(InjectorKey, undefined)
176+
const injector = ReflectiveInjector.fromResolvedProviders(
177+
resolveProviders,
178+
parent
179+
)
180+
provide(InjectorKey, injector)
181+
// 实例化
182+
resolveProviders.forEach((k) => injector.get(k.key.token))
183+
return injector
184+
}

src/extends/component.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
VNodeChild,
77
VNodeProps,
88
} from 'vue'
9-
import { getCurrentInstance, provide } from 'vue'
9+
import { getCurrentInstance, markRaw, provide } from 'vue'
1010
import { getEmitsFromProps, useCtx, useProps } from '../helper'
1111
import type {
1212
Hanlder,
@@ -86,7 +86,7 @@ export abstract class VueComponent<T extends {} = {}> {
8686
}
8787

8888
/** 渲染函数 */
89-
abstract render(ctx: ComponentPublicInstance, cache: any[]): VNodeChild
89+
abstract render?(ctx: ComponentPublicInstance, cache: any[]): VNodeChild
9090
}
9191
// 为了支持es5浏览器
9292
Object.defineProperty(VueComponent, '__vccOpts', {
@@ -116,6 +116,8 @@ Object.defineProperty(VueComponent, '__vccOpts', {
116116
// eslint-disable-next-line @typescript-eslint/no-unused-vars
117117
setup: (props: any, ctx: any) => {
118118
const instance = VueComponent.resolveComponent(CompConstructor)
119+
// 支持模板
120+
if (CompConstructor.__vccOpts__value.render) return markRaw(instance)
119121
return instance.render.bind(instance)
120122
},
121123
})

src/index.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export { Computed } from './decorators/computed'
55
export { Link } from './decorators/link'
66
export { Hook } from './decorators/hook'
77
export * from './helper'
8-
export { Component, InjectorKey, getCurrentInjector } from './di'
8+
export {
9+
Component,
10+
InjectorKey,
11+
getCurrentInjector,
12+
createCurrentInjector,
13+
} from './di'
914
export type { ComponentOptions } from './di'
1015
export type {
1116
ComponentProps,

vite.config.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { defineConfig } from 'vite'
22
import vueJsx from '@vue3-oop/plugin-vue-jsx'
3+
import vue from '@vitejs/plugin-vue'
34

45
export default defineConfig(({ command, mode }) => {
56
return {
67
plugins:
78
command === 'build'
89
? undefined
9-
: [vueJsx({ enableObjectSlots: false, slotStable: true })],
10+
: [vue(), vueJsx({ enableObjectSlots: false, slotStable: true })],
1011
resolve: {
1112
alias: [
1213
{ find: /^~/, replacement: '' },

0 commit comments

Comments
 (0)