export function render(_ctx) {
const _setTemplateRef = _createTemplateRefSetter()
const n0 = t0()
- let r0
- _renderEffect(() => r0 = _setTemplateRef(n0, _ctx.foo, r0))
+ _renderEffect(() => _setTemplateRef(n0, _ctx.foo))
return n0
}"
`;
export function render(_ctx) {
const _setTemplateRef = _createTemplateRefSetter()
const n0 = t0()
- let r0
_renderEffect(() => {
const _foo = _ctx.foo
- r0 = _setTemplateRef(n0, bar => {
+ _setTemplateRef(n0, bar => {
_foo.value = bar
;({ baz: _ctx.baz } = bar)
console.log(_foo.value, _ctx.baz)
- }, r0)
+ })
})
return n0
}"
const _setTemplateRef = _createTemplateRefSetter()
const n0 = _createFor(() => ([1,2,3]), (_for_item0) => {
const n2 = t0()
- _setTemplateRef(n2, "foo", void 0, true)
+ _setTemplateRef(n2, "foo", true)
return n2
}, undefined, 4)
return n0
flags: DynamicFlag.REFERENCED,
})
expect(ir.template).toEqual(['<div></div>'])
- expect(ir.block.operation).toMatchObject([
- {
- type: IRNodeTypes.DECLARE_OLD_REF,
- id: 0,
- },
- ])
expect(ir.block.effect).toMatchObject([
{
operations: [
])
expect(code).matchSnapshot()
expect(code).contains('const _setTemplateRef = _createTemplateRefSetter()')
- expect(code).contains('_setTemplateRef(n0, _ctx.foo, r0)')
+ expect(code).contains('_setTemplateRef(n0, _ctx.foo)')
})
test('function ref', () => {
flags: DynamicFlag.REFERENCED,
})
expect(ir.template).toEqual(['<div></div>'])
- expect(ir.block.operation).toMatchObject([
- {
- type: IRNodeTypes.DECLARE_OLD_REF,
- id: 0,
- },
- ])
expect(ir.block.effect).toMatchObject([
{
operations: [
_foo.value = bar
;({ baz: _ctx.baz } = bar)
console.log(_foo.value, _ctx.baz)
- }, r0)`)
+ })`)
})
test('ref + v-if', () => {
])
expect(code).matchSnapshot()
expect(code).contains('const _setTemplateRef = _createTemplateRefSetter()')
- expect(code).contains('_setTemplateRef(n2, "foo", void 0, true)')
+ expect(code).contains('_setTemplateRef(n2, "foo", true)')
})
})
import { genSetHtml } from './html'
import { genIf } from './if'
import { genDynamicProps, genSetProp } from './prop'
-import { genDeclareOldRef, genSetTemplateRef } from './templateRef'
+import { genSetTemplateRef } from './templateRef'
import { genGetTextChild, genSetText } from './text'
import {
type CodeFragment,
return genFor(oper, context)
case IRNodeTypes.CREATE_COMPONENT_NODE:
return genCreateComponent(oper, context)
- case IRNodeTypes.DECLARE_OLD_REF:
- return genDeclareOldRef(oper)
case IRNodeTypes.SLOT_OUTLET_NODE:
return genSlotOutlet(oper, context)
case IRNodeTypes.DIRECTIVE:
import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
-import type { DeclareOldRefIRNode, SetTemplateRefIRNode } from '../ir'
+import type { SetTemplateRefIRNode } from '../ir'
import { type CodeFragment, NEWLINE, genCall } from './utils'
import { BindingTypes, type SimpleExpressionNode } from '@vue/compiler-dom'
): CodeFragment[] {
return [
NEWLINE,
- oper.effect && `r${oper.element} = `,
...genCall(
setTemplateRefIdent, // will be generated in root scope
`n${oper.element}`,
genRefValue(oper.value, context),
- oper.effect ? `r${oper.element}` : oper.refFor ? 'void 0' : undefined,
oper.refFor && 'true',
),
]
}
-export function genDeclareOldRef(oper: DeclareOldRefIRNode): CodeFragment[] {
- return [NEWLINE, `let r${oper.id}`]
-}
-
function genRefValue(value: SimpleExpressionNode, context: CodegenContext) {
// in inline mode there is no setupState object, so we can't use string
// keys to set the ref. Instead, we need to transform it to pass the
SLOT_OUTLET_NODE,
DIRECTIVE,
- DECLARE_OLD_REF, // consider make it more general
IF,
FOR,
anchor?: number
}
-export interface DeclareOldRefIRNode extends BaseIRNode {
- type: IRNodeTypes.DECLARE_OLD_REF
- id: number
-}
-
export interface SlotOutletIRNode extends BaseIRNode {
type: IRNodeTypes.SLOT_OUTLET_NODE
id: number
| IfIRNode
| ForIRNode
| CreateComponentIRNode
- | DeclareOldRefIRNode
| SlotOutletIRNode
| GetTextChildIRNode
return () => {
const id = context.reference()
const effect = !isConstantExpression(value)
- effect &&
- context.registerOperation({
- type: IRNodeTypes.DECLARE_OLD_REF,
- id,
- })
context.registerEffect([value], {
type: IRNodeTypes.SET_TEMPLATE_REF,
element: id,
-import type { NodeRef } from '../../src/apiTemplateRef'
import {
child,
createComponent,
},
render() {
const n0 = t0()
- let r0: NodeRef | undefined
+ const setRef = createTemplateRefSetter()
renderEffect(() => {
- r0 = createTemplateRefSetter()(n0 as Element, refKey.value, r0)
+ setRef(n0 as Element, refKey.value)
})
return n0
},
const { render } = define({
render() {
const n0 = t0()
- let r0: NodeRef | undefined
+ const setRef = createTemplateRefSetter()
renderEffect(() => {
- r0 = createTemplateRefSetter()(n0 as Element, fn.value, r0)
+ setRef(n0 as Element, fn.value)
})
return n0
},
const t0 = template('<div></div>')
const { render } = define({
render() {
+ const setRef = createTemplateRefSetter()
const n0 = createIf(
() => toggle.value,
() => {
const n1 = t0()
- createTemplateRefSetter()(n1 as Element, fn)
+ setRef(n1 as Element, fn)
return n1
},
)
fooEl = useTemplateRef('foo')
barEl = useTemplateRef('bar')
const n0 = t0()
- let r0: NodeRef | undefined
+ const setRef = createTemplateRefSetter()
renderEffect(() => {
- r0 = createTemplateRefSetter()(n0 as Element, refKey.value, r0)
+ setRef(n0 as Element, refKey.value)
})
return n0
},
const instance = currentInstance!
const n0 = t0()
const n1 = t1()
- let r0: NodeRef | undefined
- let r1: NodeRef | undefined
+ const setRef = createTemplateRefSetter()
renderEffect(() => {
- r0 = createTemplateRefSetter()(
- n0 as Element,
- refToggle.value ? 'foo' : 'bar',
- r0,
- )
+ setRef(n0 as Element, refToggle.value ? 'foo' : 'bar')
})
renderEffect(() => {
- r1 = createTemplateRefSetter()(
- n1 as Element,
- refToggle.value ? 'bar' : 'foo',
- r1,
- )
+ setRef(n1 as Element, refToggle.value ? 'bar' : 'foo')
})
watchEffect(
() => {
const t1 = template('<li></li>')
const { render } = define({
render() {
+ const setRef = createTemplateRefSetter()
const n0 = createIf(
() => show.value,
() => {
() => list,
item => {
const n1 = t1()
- createTemplateRefSetter()(
- n1 as Element,
- listRefs,
- undefined,
- true,
- )
+ setRef(n1 as Element, listRefs, true)
renderEffect(() => {
setElementText(n1, item)
})
return { listRefs }
},
render() {
+ const setRef = createTemplateRefSetter()
const n0 = createIf(
() => show.value,
() => {
() => list,
item => {
const n1 = t1()
- createTemplateRefSetter()(
- n1 as Element,
- 'listRefs',
- undefined,
- true,
- )
+ setRef(n1 as Element, 'listRefs', true)
renderEffect(() => {
setElementText(n1, item)
})
const n0 = t0()
const n1 = n0.firstChild
const n2 = n1!.nextSibling!
+ const setRef = createTemplateRefSetter()
const n3 = createFor(
() => list.value,
item => {
const n4 = t1()
- createTemplateRefSetter()(
- n4 as Element,
- 'listRefs',
- undefined,
- true,
- )
+ setRef(n4 as Element, 'listRefs', true)
renderEffect(() => {
setElementText(n4, item)
})
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)
+ const oldRefMap = new WeakMap<RefEl, NodeRef | undefined>()
+ return (el, ref, refFor) => {
+ const oldRef = setRef(instance, el, ref, oldRefMap.get(el), refFor)
+ oldRefMap.set(el, oldRef)
+ return oldRef
+ }
}
/**