templateRef.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import { genExpression } from './expression'
  2. import type { CodegenContext } from '../generate'
  3. import type { DeclareOldRefIRNode, SetTemplateRefIRNode } from '../ir'
  4. import { type CodeFragment, NEWLINE, genCall } from './utils'
  5. import { BindingTypes, type SimpleExpressionNode } from '@vue/compiler-dom'
  6. export const setTemplateRefIdent = `_setTemplateRef`
  7. export function genSetTemplateRef(
  8. oper: SetTemplateRefIRNode,
  9. context: CodegenContext,
  10. ): CodeFragment[] {
  11. return [
  12. NEWLINE,
  13. oper.effect && `r${oper.element} = `,
  14. ...genCall(
  15. setTemplateRefIdent, // will be generated in root scope
  16. `n${oper.element}`,
  17. genRefValue(oper.value, context),
  18. oper.effect ? `r${oper.element}` : oper.refFor ? 'void 0' : undefined,
  19. oper.refFor && 'true',
  20. ),
  21. ]
  22. }
  23. export function genDeclareOldRef(oper: DeclareOldRefIRNode): CodeFragment[] {
  24. return [NEWLINE, `let r${oper.id}`]
  25. }
  26. function genRefValue(value: SimpleExpressionNode, context: CodegenContext) {
  27. // in inline mode there is no setupState object, so we can't use string
  28. // keys to set the ref. Instead, we need to transform it to pass the
  29. // actual ref instead.
  30. if (!__BROWSER__ && value && context.options.inline) {
  31. const binding = context.options.bindingMetadata[value.content]
  32. if (
  33. binding === BindingTypes.SETUP_LET ||
  34. binding === BindingTypes.SETUP_REF ||
  35. binding === BindingTypes.SETUP_MAYBE_REF
  36. ) {
  37. return [value.content]
  38. }
  39. }
  40. return genExpression(value, context)
  41. }