transformComponent.ts 2.5 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6 7
import {
  ComponentNode,
  findProp,
  NodeTypes,
  SimpleExpressionNode,
} from '@vue/compiler-core'
import { isUserComponent } from '@dcloudio/uni-cli-shared'
fxy060608's avatar
fxy060608 已提交
8 9 10
import { isVForScope, NodeTransform, TransformContext } from '../transform'
import { createAttributeNode, createBindDirectiveNode } from '../ast'
import { addStaticClass } from './transformElement'
fxy060608's avatar
fxy060608 已提交
11
import { ATTR_VUE_ID, CLASS_VUE_REF, CLASS_VUE_REF_IN_FOR } from './utils'
fxy060608's avatar
fxy060608 已提交
12 13
import { CodegenScope } from '../options'
import { isScopedSlotVFor } from './vSlot'
fxy060608's avatar
fxy060608 已提交
14 15

export const transformComponent: NodeTransform = (node, context) => {
fxy060608's avatar
fxy060608 已提交
16
  if (!isUserComponent(node, context as any)) {
fxy060608's avatar
fxy060608 已提交
17 18 19 20 21 22 23 24 25 26
    return
  }
  addVueRef(node, context)
  addVueId(node, context)
  return function postTransformComponent() {
    context.vueIds.pop()
  }
}

function addVueId(node: ComponentNode, context: TransformContext) {
fxy060608's avatar
fxy060608 已提交
27 28
  let { hashId, scopes, currentScope, currentVueId } = context
  if (!hashId) {
fxy060608's avatar
fxy060608 已提交
29 30
    return
  }
fxy060608's avatar
fxy060608 已提交
31
  let vueId = hashId + '-' + scopes.vueId++
fxy060608's avatar
fxy060608 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
  const indexs: string[] = []
  while (currentScope) {
    if (isVForScope(currentScope)) {
      indexs.push(`+'-'+${currentScope.indexAlias}`)
    }
    currentScope = currentScope.parent!
  }
  const inFor = !!indexs.length
  if (inFor) {
    vueId = `'${vueId}'` + indexs.reverse().join('')
  }

  context.vueIds.push(vueId)

  let value = vueId
  if (currentVueId) {
    const isParentDynamic = currentVueId.includes('+')
    const isCurrentDynamic = vueId.includes('+')
    if (isParentDynamic || isCurrentDynamic) {
      value = `(${vueId})+','+(${
        isParentDynamic ? currentVueId : `'${currentVueId}'`
      })`
    } else {
      value = vueId + ',' + currentVueId
    }
  }
  if (value.includes('+')) {
fxy060608's avatar
fxy060608 已提交
59
    return node.props.push(createBindDirectiveNode(ATTR_VUE_ID, value))
fxy060608's avatar
fxy060608 已提交
60
  }
fxy060608's avatar
fxy060608 已提交
61
  return node.props.push(createAttributeNode(ATTR_VUE_ID, value))
fxy060608's avatar
fxy060608 已提交
62 63 64
}

function addVueRef(node: ComponentNode, context: TransformContext) {
fxy060608's avatar
fxy060608 已提交
65
  // 仅配置了 ref 属性的,才需要增补 vue-ref
fxy060608's avatar
fxy060608 已提交
66 67
  const refProp = findProp(node, 'ref')
  if (!refProp) {
fxy060608's avatar
fxy060608 已提交
68 69
    return
  }
fxy060608's avatar
fxy060608 已提交
70 71 72 73 74 75
  if (refProp.type === NodeTypes.ATTRIBUTE) {
    refProp.name = 'data-ref'
  } else {
    ;(refProp.arg as SimpleExpressionNode).content = 'data-ref'
  }

fxy060608's avatar
fxy060608 已提交
76 77
  return addStaticClass(
    node,
fxy060608's avatar
fxy060608 已提交
78 79
    // vue-ref-in-for
    // vue-ref
fxy060608's avatar
fxy060608 已提交
80
    isInVFor(context.currentScope) ? CLASS_VUE_REF_IN_FOR : CLASS_VUE_REF
fxy060608's avatar
fxy060608 已提交
81 82
  )
}
fxy060608's avatar
fxy060608 已提交
83 84 85 86 87 88 89 90 91 92 93

function isInVFor(scope: CodegenScope) {
  let parent: CodegenScope | null = scope
  while (parent) {
    if (isVForScope(parent) && !isScopedSlotVFor(parent)) {
      return true
    }
    parent = parent.parent
  }
  return false
}