Skip to content

Commit

Permalink
feat: 支持模板
Browse files Browse the repository at this point in the history
  • Loading branch information
agileago committed Mar 11, 2022
1 parent a6e206d commit 9076d9c
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ coverage
commitlint.config.js
.cz-config.js
.prettierrc.js
*.vue
4 changes: 2 additions & 2 deletions example/main.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import '@abraham/reflection'
import { Component, Mut, VueComponent } from 'vue3-oop'
import { createCurrentInjector, Mut, VueComponent } from 'vue3-oop'
import { createApp } from 'vue'
import 'ant-design-vue/dist/antd.css'
import { Layout, Menu } from 'ant-design-vue'
import { RouterLink, RouterView } from 'vue-router'
import { RouterStartService } from './router'
import { routes } from './router/routes'

@Component({ providers: [RouterStartService] })
class App extends VueComponent {
injector = createCurrentInjector([RouterStartService])
@Mut() collapsed = false
render() {
return (
Expand Down
13 changes: 13 additions & 0 deletions example/module/basic/hello-world/count.comp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { type ComponentProps, VueComponent } from 'vue3-oop'

interface CountCompProps {
size: 'large' | 'small'
}

export class CountComp extends VueComponent<CountCompProps> {
static defaultProps: ComponentProps<CountCompProps> = ['size']

render() {
return <div>{this.props.size}</div>
}
}
31 changes: 31 additions & 0 deletions example/module/basic/hello-world/hello.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts">
import { getCurrentInjector, Mut, VueComponent } from 'vue3-oop'
import { CountComp } from './count.comp'
import { RouterService } from '../../../router/router.service'
export default class Hello extends VueComponent {
static components = {
CountComp,
}
@Mut() count = 1
add = () => this.count++
injector = getCurrentInjector()
router: RouterService = this.injector.get(RouterService)
constructor() {
super()
console.log(this.router)
}
}
</script>

<template>
<h2 class="abc">aaa1111</h2>
<p @click="add">{{ count }}</p>
<CountComp size="large"></CountComp>
</template>

<style lang="scss" scoped>
.abc {
color: red;
}
</style>
2 changes: 1 addition & 1 deletion example/router/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const routes: RouteRecordRaw[] = [
children: [
{
path: '/basic/hello-world',
component: () => import('../module/basic/hello-world/hello-world.view'),
component: () => import('../module/basic/hello-world/hello.vue'),
meta: {
title: 'Hello Wolrd',
},
Expand Down
21 changes: 21 additions & 0 deletions src/di/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function resolveComponent(target: { new (...args: []): any }) {
// 如果没有使用 injection-js 则不创建注入器
if (!Reflect.getMetadata('annotations', target)) return new target()
const parent = inject(InjectorKey, undefined)
// 从缓存中拿到解析过得依赖
let resolveProviders = Reflect.getOwnMetadata<ResolvedReflectiveProvider[]>(
MetadataProviderKey,
target
Expand Down Expand Up @@ -161,3 +162,23 @@ export function getCurrentInjector(): ReflectiveInjector {
// @ts-ignore
return instance.provides[InjectorKey] || inject(InjectorKey)
}
/** 手动创建当前注射器, 只能用在 setup 中 */
export function createCurrentInjector(
providers: Provider[],
exclude?: Provider[]
): ReflectiveInjector {
let deps = resolveDependencies(providers)
if (exclude?.length) {
deps = deps.filter((k) => exclude?.includes(k))
}
const resolveProviders = ReflectiveInjector.resolve(deps)
const parent = inject(InjectorKey, undefined)
const injector = ReflectiveInjector.fromResolvedProviders(
resolveProviders,
parent
)
provide(InjectorKey, injector)
// 实例化
resolveProviders.forEach((k) => injector.get(k.key.token))
return injector
}
6 changes: 4 additions & 2 deletions src/extends/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
VNodeChild,
VNodeProps,
} from 'vue'
import { getCurrentInstance, provide } from 'vue'
import { getCurrentInstance, markRaw, provide } from 'vue'
import { getEmitsFromProps, useCtx, useProps } from '../helper'
import type {
Hanlder,
Expand Down Expand Up @@ -86,7 +86,7 @@ export abstract class VueComponent<T extends {} = {}> {
}

/** 渲染函数 */
abstract render(ctx: ComponentPublicInstance, cache: any[]): VNodeChild
abstract render?(ctx: ComponentPublicInstance, cache: any[]): VNodeChild
}
// 为了支持es5浏览器
Object.defineProperty(VueComponent, '__vccOpts', {
Expand Down Expand Up @@ -116,6 +116,8 @@ Object.defineProperty(VueComponent, '__vccOpts', {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setup: (props: any, ctx: any) => {
const instance = VueComponent.resolveComponent(CompConstructor)
// 支持模板
if (CompConstructor.__vccOpts__value.render) return markRaw(instance)
return instance.render.bind(instance)
},
})
Expand Down
7 changes: 6 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ export { Computed } from './decorators/computed'
export { Link } from './decorators/link'
export { Hook } from './decorators/hook'
export * from './helper'
export { Component, InjectorKey, getCurrentInjector } from './di'
export {
Component,
InjectorKey,
getCurrentInjector,
createCurrentInjector,
} from './di'
export type { ComponentOptions } from './di'
export type {
ComponentProps,
Expand Down
3 changes: 2 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { defineConfig } from 'vite'
import vueJsx from '@vue3-oop/plugin-vue-jsx'
import vue from '@vitejs/plugin-vue'

export default defineConfig(({ command, mode }) => {
return {
plugins:
command === 'build'
? undefined
: [vueJsx({ enableObjectSlots: false, slotStable: true })],
: [vue(), vueJsx({ enableObjectSlots: false, slotStable: true })],
resolve: {
alias: [
{ find: /^~/, replacement: '' },
Expand Down

0 comments on commit 9076d9c

Please sign in to comment.