mirror of https://github.com/vuejs/core.git
wip(vapor): templateRef adjustments
This commit is contained in:
parent
e38805354d
commit
0d1df25f23
|
@ -16,6 +16,7 @@ import {
|
|||
codeFragmentToString,
|
||||
genCall,
|
||||
} from './generators/utils'
|
||||
import { setTemplateRefIdent } from './generators/templateRef'
|
||||
|
||||
export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
|
||||
|
||||
|
@ -110,19 +111,21 @@ export function generate(
|
|||
', ',
|
||||
)
|
||||
|
||||
if (inline) {
|
||||
// push(`((${signature}) => {`)
|
||||
} else {
|
||||
if (!inline) {
|
||||
push(NEWLINE, `export function ${functionName}(${signature}) {`)
|
||||
}
|
||||
|
||||
push(INDENT_START)
|
||||
if (ir.hasTemplateRef) {
|
||||
push(
|
||||
NEWLINE,
|
||||
`const ${setTemplateRefIdent} = ${context.helper('createTemplateRefSetter')}()`,
|
||||
)
|
||||
}
|
||||
push(...genBlockContent(ir.block, context, true))
|
||||
push(INDENT_END, NEWLINE)
|
||||
|
||||
if (inline) {
|
||||
// push('})()')
|
||||
} else {
|
||||
if (!inline) {
|
||||
push('}')
|
||||
}
|
||||
|
||||
|
|
|
@ -67,9 +67,14 @@ export function genOperation(
|
|||
return genDeclareOldRef(oper)
|
||||
case IRNodeTypes.SLOT_OUTLET_NODE:
|
||||
return genSlotOutlet(oper, context)
|
||||
case IRNodeTypes.WITH_DIRECTIVE:
|
||||
return [] // TODO
|
||||
default:
|
||||
const exhaustiveCheck: never = oper
|
||||
throw new Error(
|
||||
`Unhandled operation type in genOperation: ${exhaustiveCheck}`,
|
||||
)
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
export function genEffects(
|
||||
|
|
|
@ -3,16 +3,17 @@ import type { CodegenContext } from '../generate'
|
|||
import type { DeclareOldRefIRNode, SetTemplateRefIRNode } from '../ir'
|
||||
import { type CodeFragment, NEWLINE, genCall } from './utils'
|
||||
|
||||
export const setTemplateRefIdent = `_setTemplateRef`
|
||||
|
||||
export function genSetTemplateRef(
|
||||
oper: SetTemplateRefIRNode,
|
||||
context: CodegenContext,
|
||||
): CodeFragment[] {
|
||||
const { helper } = context
|
||||
return [
|
||||
NEWLINE,
|
||||
oper.effect && `r${oper.element} = `,
|
||||
...genCall(
|
||||
helper('setRef'),
|
||||
setTemplateRefIdent, // will be generated in root scope
|
||||
`n${oper.element}`,
|
||||
genExpression(oper.value, context),
|
||||
oper.effect ? `r${oper.element}` : oper.refFor ? 'void 0' : undefined,
|
||||
|
|
|
@ -63,6 +63,7 @@ export interface RootIRNode {
|
|||
component: Set<string>
|
||||
directive: Set<string>
|
||||
block: BlockIRNode
|
||||
hasTemplateRef: boolean
|
||||
}
|
||||
|
||||
export interface IfIRNode extends BaseIRNode {
|
||||
|
|
|
@ -220,6 +220,7 @@ export function transform(
|
|||
component: new Set(),
|
||||
directive: new Set(),
|
||||
block: newBlock(node),
|
||||
hasTemplateRef: false,
|
||||
}
|
||||
|
||||
const context = new TransformContext(ir, node, options)
|
||||
|
|
|
@ -15,6 +15,8 @@ export const transformTemplateRef: NodeTransform = (node, context) => {
|
|||
const dir = findProp(node, 'ref', false, true)
|
||||
if (!dir) return
|
||||
|
||||
context.ir.hasTemplateRef = true
|
||||
|
||||
let value: SimpleExpressionNode
|
||||
if (dir.type === NodeTypes.DIRECTIVE) {
|
||||
value = dir.exp || normalizeBindShorthand(dir.arg!, context)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { type ShallowRef, readonly, shallowRef } from '@vue/reactivity'
|
||||
import { getCurrentInstance } from '../component'
|
||||
import { getCurrentGenericInstance } from '../component'
|
||||
import { warn } from '../warning'
|
||||
import { EMPTY_OBJ } from '@vue/shared'
|
||||
|
||||
|
@ -8,7 +8,7 @@ export const knownTemplateRefs: WeakSet<ShallowRef> = new WeakSet()
|
|||
export function useTemplateRef<T = unknown, Keys extends string = string>(
|
||||
key: Keys,
|
||||
): Readonly<ShallowRef<T | null>> {
|
||||
const i = getCurrentInstance()
|
||||
const i = getCurrentGenericInstance()
|
||||
const r = shallowRef(null)
|
||||
if (i) {
|
||||
const refs = i.refs === EMPTY_OBJ ? (i.refs = {}) : i.refs
|
||||
|
|
|
@ -7,7 +7,8 @@ import {
|
|||
} from '../directives/vShow'
|
||||
import { CSS_VAR_TEXT } from '../helpers/useCssVars'
|
||||
|
||||
type Style = string | Record<string, string | string[]> | null | undefined
|
||||
type Style = StyleValue | Record<string, StyleValue | StyleValue[]>
|
||||
type StyleValue = string | null | undefined
|
||||
|
||||
const displayRE = /(^|;)\s*display\s*:/
|
||||
|
||||
|
@ -70,7 +71,7 @@ const importantRE = /\s*!important$/
|
|||
function setStyle(
|
||||
style: CSSStyleDeclaration,
|
||||
name: string,
|
||||
val: string | string[],
|
||||
val: StyleValue | StyleValue[],
|
||||
) {
|
||||
if (isArray(val)) {
|
||||
val.forEach(v => setStyle(style, name, v))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ref, shallowRef } from '@vue/reactivity'
|
||||
import { type VaporComponentInstance, createComponent } from '../src/component'
|
||||
import { setRef } from '../src/dom/templateRef'
|
||||
import { setRef } from '../src/apiTemplateRef'
|
||||
import { makeRender } from './_utils'
|
||||
import { currentInstance } from '@vue/runtime-dom'
|
||||
import { defineVaporComponent } from '../src/apiDefineComponent'
|
||||
|
@ -8,7 +8,8 @@ import { defineVaporComponent } from '../src/apiDefineComponent'
|
|||
const define = makeRender()
|
||||
|
||||
describe('api: expose', () => {
|
||||
test.todo('via setup context + template ref', () => {
|
||||
test('via setup context + template ref', () => {
|
||||
let i: any
|
||||
const Child = defineVaporComponent({
|
||||
setup(_, { expose }) {
|
||||
expose({
|
||||
|
@ -20,19 +21,20 @@ describe('api: expose', () => {
|
|||
})
|
||||
const childRef = ref()
|
||||
define({
|
||||
render: () => {
|
||||
const n0 = createComponent(Child)
|
||||
setup: () => {
|
||||
const n0 = (i = createComponent(Child))
|
||||
setRef(currentInstance as VaporComponentInstance, n0, childRef)
|
||||
return n0
|
||||
},
|
||||
}).render()
|
||||
|
||||
expect(childRef.value).toBeTruthy()
|
||||
expect(childRef.value).toBe(i.exposeProxy)
|
||||
expect(childRef.value.foo).toBe(1)
|
||||
expect(childRef.value.bar).toBe(2)
|
||||
expect(childRef.value.baz).toBeUndefined()
|
||||
})
|
||||
|
||||
test.todo('via setup context + template ref (expose empty)', () => {
|
||||
test('via setup context + template ref (expose empty)', () => {
|
||||
let childInstance: VaporComponentInstance | null = null
|
||||
const Child = defineVaporComponent({
|
||||
setup(_) {
|
||||
|
@ -42,14 +44,14 @@ describe('api: expose', () => {
|
|||
})
|
||||
const childRef = shallowRef()
|
||||
define({
|
||||
render: () => {
|
||||
setup: () => {
|
||||
const n0 = createComponent(Child)
|
||||
setRef(n0, childRef)
|
||||
setRef(currentInstance as VaporComponentInstance, n0, childRef)
|
||||
return n0
|
||||
},
|
||||
}).render()
|
||||
|
||||
expect(childInstance!.exposed).toBeUndefined()
|
||||
expect(childInstance!.exposed).toBeNull()
|
||||
expect(childRef.value).toBe(childInstance!)
|
||||
})
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import type { NodeRef } from '../../src/dom/templateRef'
|
||||
import type { NodeRef } from '../../src/apiTemplateRef'
|
||||
import {
|
||||
createFor,
|
||||
createIf,
|
||||
createTemplateRefSetter,
|
||||
insert,
|
||||
renderEffect,
|
||||
setRef,
|
||||
setText,
|
||||
template,
|
||||
} from '../../src'
|
||||
|
@ -19,7 +19,7 @@ import {
|
|||
|
||||
const define = makeRender()
|
||||
|
||||
describe.todo('api: template ref', () => {
|
||||
describe('api: template ref', () => {
|
||||
test('string ref mount', () => {
|
||||
const t0 = template('<div ref="refKey"></div>')
|
||||
const el = ref(null)
|
||||
|
@ -31,7 +31,7 @@ describe.todo('api: template ref', () => {
|
|||
},
|
||||
render() {
|
||||
const n0 = t0()
|
||||
setRef(n0 as Element, 'refKey')
|
||||
createTemplateRefSetter()(n0 as Element, 'refKey')
|
||||
return n0
|
||||
},
|
||||
})
|
||||
|
@ -57,7 +57,7 @@ describe.todo('api: template ref', () => {
|
|||
const n0 = t0()
|
||||
let r0: NodeRef | undefined
|
||||
renderEffect(() => {
|
||||
r0 = setRef(n0 as Element, refKey.value, r0)
|
||||
r0 = createTemplateRefSetter()(n0 as Element, refKey.value, r0)
|
||||
})
|
||||
return n0
|
||||
},
|
||||
|
@ -72,7 +72,7 @@ describe.todo('api: template ref', () => {
|
|||
expect(fooEl.value).toBe(null)
|
||||
})
|
||||
|
||||
it('string ref unmount', async () => {
|
||||
it.todo('string ref unmount', async () => {
|
||||
const t0 = template('<div></div>')
|
||||
const el = ref(null)
|
||||
const toggle = ref(true)
|
||||
|
@ -84,6 +84,7 @@ describe.todo('api: template ref', () => {
|
|||
}
|
||||
},
|
||||
render() {
|
||||
const setRef = createTemplateRefSetter()
|
||||
const n0 = createIf(
|
||||
() => toggle.value,
|
||||
() => {
|
||||
|
@ -109,7 +110,7 @@ describe.todo('api: template ref', () => {
|
|||
const { render } = define({
|
||||
render() {
|
||||
const n0 = t0()
|
||||
setRef(n0 as Element, fn)
|
||||
createTemplateRefSetter()(n0 as Element, fn)
|
||||
return n0
|
||||
},
|
||||
})
|
||||
|
@ -129,7 +130,7 @@ describe.todo('api: template ref', () => {
|
|||
const n0 = t0()
|
||||
let r0: NodeRef | undefined
|
||||
renderEffect(() => {
|
||||
r0 = setRef(n0 as Element, fn.value, r0)
|
||||
r0 = createTemplateRefSetter()(n0 as Element, fn.value, r0)
|
||||
})
|
||||
return n0
|
||||
},
|
||||
|
@ -148,7 +149,7 @@ describe.todo('api: template ref', () => {
|
|||
expect(fn2.mock.calls[0][0]).toBe(host.children[0])
|
||||
})
|
||||
|
||||
it('function ref unmount', async () => {
|
||||
it.todo('function ref unmount', async () => {
|
||||
const fn = vi.fn()
|
||||
const toggle = ref(true)
|
||||
|
||||
|
@ -159,7 +160,7 @@ describe.todo('api: template ref', () => {
|
|||
() => toggle.value,
|
||||
() => {
|
||||
const n1 = t0()
|
||||
setRef(n1 as Element, fn)
|
||||
createTemplateRefSetter()(n1 as Element, fn)
|
||||
return n1
|
||||
},
|
||||
)
|
||||
|
@ -185,7 +186,7 @@ describe.todo('api: template ref', () => {
|
|||
},
|
||||
render() {
|
||||
const n0 = t0()
|
||||
setRef(n0 as Element, 'refKey')
|
||||
createTemplateRefSetter()(n0 as Element, 'refKey')
|
||||
return n0
|
||||
},
|
||||
})
|
||||
|
@ -213,9 +214,9 @@ describe.todo('api: template ref', () => {
|
|||
const n0 = t0()
|
||||
const n1 = t1()
|
||||
const n2 = t2()
|
||||
setRef(n0 as Element, 'refKey1')
|
||||
setRef(n1 as Element, 'refKey2')
|
||||
setRef(n2 as Element, 'refKey3')
|
||||
createTemplateRefSetter()(n0 as Element, 'refKey1')
|
||||
createTemplateRefSetter()(n1 as Element, 'refKey2')
|
||||
createTemplateRefSetter()(n2 as Element, 'refKey3')
|
||||
return [n0, n1, n2]
|
||||
},
|
||||
})
|
||||
|
@ -234,7 +235,7 @@ describe.todo('api: template ref', () => {
|
|||
const { render } = define({
|
||||
render() {
|
||||
const n0 = t0()
|
||||
setRef(n0 as Element, el)
|
||||
createTemplateRefSetter()(n0 as Element, el)
|
||||
renderEffect(() => {
|
||||
setText(n0, el.value && el.value.getAttribute('id'))
|
||||
})
|
||||
|
@ -265,10 +266,18 @@ describe.todo('api: template ref', () => {
|
|||
let r0: NodeRef | undefined
|
||||
let r1: NodeRef | undefined
|
||||
renderEffect(() => {
|
||||
r0 = setRef(n0 as Element, refToggle.value ? 'foo' : 'bar', r0)
|
||||
r0 = createTemplateRefSetter()(
|
||||
n0 as Element,
|
||||
refToggle.value ? 'foo' : 'bar',
|
||||
r0,
|
||||
)
|
||||
})
|
||||
renderEffect(() => {
|
||||
r1 = setRef(n1 as Element, refToggle.value ? 'bar' : 'foo', r1)
|
||||
r1 = createTemplateRefSetter()(
|
||||
n1 as Element,
|
||||
refToggle.value ? 'bar' : 'foo',
|
||||
r1,
|
||||
)
|
||||
})
|
||||
watchEffect(
|
||||
() => {
|
||||
|
@ -297,7 +306,7 @@ describe.todo('api: template ref', () => {
|
|||
})
|
||||
|
||||
// #1789
|
||||
test('toggle the same ref to different elements', async () => {
|
||||
test.todo('toggle the same ref to different elements', async () => {
|
||||
const refToggle = ref(false)
|
||||
const spy = vi.fn()
|
||||
|
||||
|
@ -306,6 +315,7 @@ describe.todo('api: template ref', () => {
|
|||
const { render } = define({
|
||||
render() {
|
||||
const instance = currentInstance!
|
||||
const setRef = createTemplateRefSetter()
|
||||
const n0 = createIf(
|
||||
() => refToggle.value,
|
||||
() => {
|
||||
|
@ -341,7 +351,7 @@ describe.todo('api: template ref', () => {
|
|||
})
|
||||
|
||||
// compiled output of v-for + template ref
|
||||
test('ref in v-for', async () => {
|
||||
test.todo('ref in v-for', async () => {
|
||||
const show = ref(true)
|
||||
const list = reactive([1, 2, 3])
|
||||
const listRefs = ref([])
|
||||
|
@ -359,7 +369,12 @@ describe.todo('api: template ref', () => {
|
|||
() => list,
|
||||
state => {
|
||||
const n1 = t1()
|
||||
setRef(n1 as Element, listRefs, undefined, true)
|
||||
createTemplateRefSetter()(
|
||||
n1 as Element,
|
||||
listRefs,
|
||||
undefined,
|
||||
true,
|
||||
)
|
||||
renderEffect(() => {
|
||||
const [item] = state
|
||||
setText(n1, item)
|
||||
|
@ -396,7 +411,7 @@ describe.todo('api: template ref', () => {
|
|||
expect(mapRefs()).toMatchObject(['2', '3', '4'])
|
||||
})
|
||||
|
||||
test('named ref in v-for', async () => {
|
||||
test.todo('named ref in v-for', async () => {
|
||||
const show = ref(true)
|
||||
const list = reactive([1, 2, 3])
|
||||
const listRefs = ref([])
|
||||
|
@ -417,7 +432,12 @@ describe.todo('api: template ref', () => {
|
|||
() => list,
|
||||
state => {
|
||||
const n1 = t1()
|
||||
setRef(n1 as Element, 'listRefs', undefined, true)
|
||||
createTemplateRefSetter()(
|
||||
n1 as Element,
|
||||
'listRefs',
|
||||
undefined,
|
||||
true,
|
||||
)
|
||||
renderEffect(() => {
|
||||
const [item] = state
|
||||
setText(n1, item)
|
||||
|
@ -455,59 +475,67 @@ describe.todo('api: template ref', () => {
|
|||
})
|
||||
|
||||
// #6697 v-for ref behaves differently under production and development
|
||||
test('named ref in v-for , should be responsive when rendering', async () => {
|
||||
const list = ref([1, 2, 3])
|
||||
const listRefs = ref([])
|
||||
test.todo(
|
||||
'named ref in v-for , should be responsive when rendering',
|
||||
async () => {
|
||||
const list = ref([1, 2, 3])
|
||||
const listRefs = ref([])
|
||||
|
||||
const t0 = template('<div><div></div><ul></ul></div>')
|
||||
const t1 = template('<li></li>')
|
||||
const { render } = define({
|
||||
setup() {
|
||||
return { listRefs }
|
||||
},
|
||||
render() {
|
||||
const n0 = t0()
|
||||
const n1 = n0.firstChild
|
||||
const n2 = n1!.nextSibling!
|
||||
const n3 = createFor(
|
||||
() => list.value,
|
||||
state => {
|
||||
const n4 = t1()
|
||||
setRef(n4 as Element, 'listRefs', undefined, true)
|
||||
renderEffect(() => {
|
||||
const [item] = state
|
||||
setText(n4, item)
|
||||
})
|
||||
return n4
|
||||
},
|
||||
)
|
||||
insert(n3, n2 as unknown as ParentNode)
|
||||
renderEffect(() => {
|
||||
setText(n1!, String(listRefs.value))
|
||||
})
|
||||
return n0
|
||||
},
|
||||
})
|
||||
const t0 = template('<div><div></div><ul></ul></div>')
|
||||
const t1 = template('<li></li>')
|
||||
const { render } = define({
|
||||
setup() {
|
||||
return { listRefs }
|
||||
},
|
||||
render() {
|
||||
const n0 = t0()
|
||||
const n1 = n0.firstChild
|
||||
const n2 = n1!.nextSibling!
|
||||
const n3 = createFor(
|
||||
() => list.value,
|
||||
state => {
|
||||
const n4 = t1()
|
||||
createTemplateRefSetter()(
|
||||
n4 as Element,
|
||||
'listRefs',
|
||||
undefined,
|
||||
true,
|
||||
)
|
||||
renderEffect(() => {
|
||||
const [item] = state
|
||||
setText(n4, item)
|
||||
})
|
||||
return n4
|
||||
},
|
||||
)
|
||||
insert(n3, n2 as unknown as ParentNode)
|
||||
renderEffect(() => {
|
||||
setText(n1!, String(listRefs.value))
|
||||
})
|
||||
return n0
|
||||
},
|
||||
})
|
||||
|
||||
const { host } = render()
|
||||
const { host } = render()
|
||||
|
||||
await nextTick()
|
||||
expect(String(listRefs.value)).toBe(
|
||||
'[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]',
|
||||
)
|
||||
expect(host.innerHTML).toBe(
|
||||
'<div><div>[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>1</li><li>2</li><li>3</li><!--for--></ul></div>',
|
||||
)
|
||||
await nextTick()
|
||||
expect(String(listRefs.value)).toBe(
|
||||
'[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]',
|
||||
)
|
||||
expect(host.innerHTML).toBe(
|
||||
'<div><div>[object HTMLLIElement],[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>1</li><li>2</li><li>3</li><!--for--></ul></div>',
|
||||
)
|
||||
|
||||
list.value.splice(0, 1)
|
||||
await nextTick()
|
||||
expect(String(listRefs.value)).toBe(
|
||||
'[object HTMLLIElement],[object HTMLLIElement]',
|
||||
)
|
||||
expect(host.innerHTML).toBe(
|
||||
'<div><div>[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>2</li><li>3</li><!--for--></ul></div>',
|
||||
)
|
||||
})
|
||||
list.value.splice(0, 1)
|
||||
await nextTick()
|
||||
expect(String(listRefs.value)).toBe(
|
||||
'[object HTMLLIElement],[object HTMLLIElement]',
|
||||
)
|
||||
expect(host.innerHTML).toBe(
|
||||
'<div><div>[object HTMLLIElement],[object HTMLLIElement]</div><ul><li>2</li><li>3</li><!--for--></ul></div>',
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
// TODO: need to implement Component slots
|
||||
// test('string ref inside slots', async () => {
|
||||
|
@ -523,7 +551,7 @@ describe.todo('api: template ref', () => {
|
|||
// spy(this.$refs.foo.tag)
|
||||
// })
|
||||
// const n0 = createComponent(Child)
|
||||
// setRef(n0, 'foo')
|
||||
// createTemplateRefSetter()(n0, 'foo')
|
||||
// return n0
|
||||
// },
|
||||
// })
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
import { createComponent, setRef, template } from '../src'
|
||||
import { makeRender } from './_utils'
|
||||
import type { VaporComponent } from '../src/component'
|
||||
import type { RefEl } from '../src/dom/templateRef'
|
||||
import type { RefEl } from '../src/apiTemplateRef'
|
||||
|
||||
const define = makeRender()
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
currentInstance,
|
||||
getExposed,
|
||||
isVaporComponent,
|
||||
} from '../component'
|
||||
} from './component'
|
||||
import {
|
||||
type SchedulerJob,
|
||||
callWithErrorHandling,
|
||||
|
@ -23,30 +23,41 @@ import {
|
|||
export type NodeRef = string | Ref | ((ref: Element) => void)
|
||||
export type RefEl = Element | VaporComponentInstance
|
||||
|
||||
export type setRefFn = (
|
||||
el: RefEl,
|
||||
ref: NodeRef,
|
||||
oldRef?: NodeRef,
|
||||
refFor?: boolean,
|
||||
) => NodeRef | undefined
|
||||
|
||||
export function createTemplateRefSetter(): setRefFn {
|
||||
const instance = currentInstance as VaporComponentInstance
|
||||
return (...args) => setRef(instance, ...args)
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for handling a template ref
|
||||
*/
|
||||
export function setRef(
|
||||
instance: VaporComponentInstance,
|
||||
el: RefEl,
|
||||
ref: NodeRef,
|
||||
oldRef?: NodeRef,
|
||||
refFor = false,
|
||||
): NodeRef | undefined {
|
||||
if (!currentInstance || currentInstance.isUnmounted) return
|
||||
if (!instance || instance.isUnmounted) return
|
||||
|
||||
const setupState = currentInstance.setupState || {}
|
||||
const setupState: any = __DEV__ ? instance.setupState || {} : null
|
||||
const refValue = isVaporComponent(el) ? getExposed(el) || el : el
|
||||
|
||||
const refs =
|
||||
currentInstance.refs === EMPTY_OBJ
|
||||
? (currentInstance.refs = {})
|
||||
: currentInstance.refs
|
||||
instance.refs === EMPTY_OBJ ? (instance.refs = {}) : instance.refs
|
||||
|
||||
// dynamic ref changed. unset old ref
|
||||
if (oldRef != null && oldRef !== ref) {
|
||||
if (isString(oldRef)) {
|
||||
refs[oldRef] = null
|
||||
if (hasOwn(setupState, oldRef)) {
|
||||
if (__DEV__ && hasOwn(setupState, oldRef)) {
|
||||
setupState[oldRef] = null
|
||||
}
|
||||
} else if (isRef(oldRef)) {
|
||||
|
@ -66,6 +77,7 @@ export function setRef(
|
|||
}
|
||||
|
||||
invokeRefSetter(refValue)
|
||||
// TODO this gets called repeatedly in renderEffect when it's dynamic ref?
|
||||
onScopeDispose(() => invokeRefSetter())
|
||||
} else {
|
||||
const _isString = isString(ref)
|
||||
|
@ -76,7 +88,7 @@ export function setRef(
|
|||
const doSet: SchedulerJob = () => {
|
||||
if (refFor) {
|
||||
existing = _isString
|
||||
? hasOwn(setupState, ref)
|
||||
? __DEV__ && hasOwn(setupState, ref)
|
||||
? setupState[ref]
|
||||
: refs[ref]
|
||||
: ref.value
|
||||
|
@ -85,7 +97,7 @@ export function setRef(
|
|||
existing = [refValue]
|
||||
if (_isString) {
|
||||
refs[ref] = existing
|
||||
if (hasOwn(setupState, ref)) {
|
||||
if (__DEV__ && hasOwn(setupState, ref)) {
|
||||
setupState[ref] = refs[ref]
|
||||
// if setupState[ref] is a reactivity ref,
|
||||
// the existing will also become reactivity too
|
||||
|
@ -100,7 +112,7 @@ export function setRef(
|
|||
}
|
||||
} else if (_isString) {
|
||||
refs[ref] = refValue
|
||||
if (hasOwn(setupState, ref)) {
|
||||
if (__DEV__ && hasOwn(setupState, ref)) {
|
||||
setupState[ref] = refValue
|
||||
}
|
||||
} else if (_isRef) {
|
||||
|
@ -112,13 +124,14 @@ export function setRef(
|
|||
doSet.id = -1
|
||||
queuePostFlushCb(doSet)
|
||||
|
||||
// TODO this gets called repeatedly in renderEffect when it's dynamic ref?
|
||||
onScopeDispose(() => {
|
||||
queuePostFlushCb(() => {
|
||||
if (isArray(existing)) {
|
||||
remove(existing, refValue)
|
||||
} else if (_isString) {
|
||||
refs[ref] = null
|
||||
if (hasOwn(setupState, ref)) {
|
||||
if (__DEV__ && hasOwn(setupState, ref)) {
|
||||
setupState[ref] = null
|
||||
}
|
||||
} else if (_isRef) {
|
||||
|
@ -127,7 +140,7 @@ export function setRef(
|
|||
})
|
||||
})
|
||||
} else if (__DEV__) {
|
||||
// warn('Invalid template ref type:', ref, `(${typeof ref})`)
|
||||
warn('Invalid template ref type:', ref, `(${typeof ref})`)
|
||||
}
|
||||
}
|
||||
return ref
|
|
@ -31,6 +31,7 @@ import {
|
|||
pauseTracking,
|
||||
proxyRefs,
|
||||
resetTracking,
|
||||
unref,
|
||||
} from '@vue/reactivity'
|
||||
import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
|
||||
import {
|
||||
|
@ -485,7 +486,9 @@ export function getExposed(
|
|||
if (instance.exposed) {
|
||||
return (
|
||||
instance.exposeProxy ||
|
||||
(instance.exposeProxy = proxyRefs(markRaw(instance.exposed)))
|
||||
(instance.exposeProxy = new Proxy(markRaw(instance.exposed), {
|
||||
get: (target, key) => unref(target[key as any]),
|
||||
}))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,4 +25,4 @@ export {
|
|||
export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
|
||||
export { createIf } from './apiCreateIf'
|
||||
export { createFor } from './apiCreateFor'
|
||||
export { setRef } from './dom/templateRef'
|
||||
export { createTemplateRefSetter } from './apiTemplateRef'
|
||||
|
|
Loading…
Reference in New Issue