Skip to content

Commit

Permalink
feat: 增加useForwardRef
Browse files Browse the repository at this point in the history
  • Loading branch information
agileago committed Mar 16, 2022
1 parent 84e4108 commit 8a3c963
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 13 deletions.
51 changes: 48 additions & 3 deletions example/module/basic/hello-world/hello-world.view.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,53 @@
import { Mut, VueComponent } from 'vue3-oop'
import { Hook, Link, useForwardRef, VueComponent } from 'vue3-oop'
import { Input, type InputProps } from 'ant-design-vue'
import { ref } from 'vue'

function createBigSizeInput(size: 'small' | 'middle' | 'large') {
class BigInput extends VueComponent<Omit<InputProps, 'size'>> {
forwardRef = useForwardRef()

render() {
return (
<Input
{...this.context.attrs}
ref={this.forwardRef}
size={size}
></Input>
)
}
}
return BigInput
}

const BigInput = createBigSizeInput('large')

class Abc extends VueComponent {
a = ref(0)

render() {
return <div>{this.a.value}</div>
}
}

export default class HelloWorldView extends VueComponent {
@Mut() msg = 'hello world'
@Link() abc: Abc[]

@Link() input: any

@Hook('Mounted')
mounted() {
console.log(this.abc)
console.log(this.input)
}
render() {
return <h1>{this.msg}</h1>
return (
<div>
<button onClick={() => this.abc}>+</button>
<Abc ref_for ref_key={'abc'} ref={'abc'}></Abc>
<Abc ref_for ref_key={'abc'} ref={'abc'}></Abc>
<Abc ref_for ref_key={'abc'} ref={'abc'}></Abc>
<BigInput ref={'input'}></BigInput>
</div>
)
}
}
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.vue'),
component: () => import('../module/basic/hello-world/hello-world.view'),
meta: {
title: 'Hello Wolrd',
},
Expand Down
57 changes: 49 additions & 8 deletions src/extends/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type VueComponentProps<T extends {}> = Omit<T, 'slots'> &
AllowedComponentProps &
Record<string, unknown>

// @ts-ignore
export abstract class VueComponent<T extends {} = {}> {
/** 热更新使用 */
static __hmrId?: string
Expand All @@ -49,25 +50,54 @@ export abstract class VueComponent<T extends {} = {}> {
static globalStore?: boolean
/** 是否把自己当做服务provide出去,以便子组件可注入 */
static ProviderKey?: string | symbol | number | InjectionKey<any>
/** 主要给jsx提示用 */
get $props() {
return this.props
}
/** 组件属性 */
public props = useProps<VueComponentProps<T>>()
/** 组件上下文 */
public context = useCtx() as WithSlotTypes<T>
/** 组件内部实例,如果使用组件实例请 this.$.proxy */
public $ = getCurrentInstance()!
/** 主要给jsx提示用 */
get $props() {
return this.props
}
get $el() {
return this.$.proxy?.$el
}
get $refs() {
return this.$.proxy?.$refs
}
get $parent() {
return this.$.proxy?.$parent
}
get $root() {
return this.$.proxy?.$root
}
get $emit() {
return this.$.proxy?.$emit
}
get $forceUpdate() {
return this.$.proxy?.$forceUpdate
}
get $nextTick() {
return this.$.proxy?.$nextTick
}
get $watch() {
return this.$.proxy?.$watch
}

constructor() {
this.context.expose(this)
markRaw(this)
// 处理ref
const current = this.$
// 由于vue会包装一层,会自动代理ref,导致类型错误, 还导致不能修改变量
current.exposed = this
current.exposeProxy = this

// 处理依赖注入
const ThisConstructor = this.constructor as VueComponentStaticContructor
if (ThisConstructor.ProviderKey) provide(ThisConstructor.ProviderKey, this)
if (ThisConstructor.globalStore) {
// 如果作为全局的服务,则注入到根上面
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const current = getCurrentInstance()!
const app = current.appContext.app
app.provide(GlobalStoreKey, this)
app.getStore = () => this
Expand All @@ -82,13 +112,14 @@ export abstract class VueComponent<T extends {} = {}> {
return current?.provides[token]
}
}

VueComponent.handler.forEach((handler) => handler.handler(this))
}

/** 渲染函数 */
render?(ctx: ComponentPublicInstance, cache: any[]): VNodeChild
}
// 为了支持es5浏览器
// 某些浏览器不支持 static get
Object.defineProperty(VueComponent, '__vccOpts', {
enumerable: true,
configurable: true,
Expand Down Expand Up @@ -123,3 +154,13 @@ Object.defineProperty(VueComponent, '__vccOpts', {
})
},
})

// 处理forwardref
export function useForwardRef() {
const instance = getCurrentInstance()!
function forwardRef(ref: any) {
instance.exposed = ref
instance.exposeProxy = ref
}
return forwardRef
}
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
export { VueComponent, GlobalStoreKey } from './extends/component'
export {
VueComponent,
GlobalStoreKey,
useForwardRef,
} from './extends/component'
export { VueService, ProviderKey } from './extends/service'
export { Mut } from './decorators/mut'
export { Computed } from './decorators/computed'
Expand Down

0 comments on commit 8a3c963

Please sign in to comment.