util.js 4.0 KB
Newer Older
fxy060608's avatar
init v3  
fxy060608 已提交
1 2 3 4
const VARS = ['true', 'false', 'null']
const NUMBER_RE = /^-?\d*(\.\d+)?$/

const ID = '_i'
fxy060608's avatar
fxy060608 已提交
5 6
const ITERATOR1 = '$1'
const ITERATOR2 = '$2'
fxy060608's avatar
fxy060608 已提交
7 8 9
const ITERATOR3 = '$3'
const SET_DATA = '_$s'
const GET_DATA = '_$g'
fxy060608's avatar
init v3  
fxy060608 已提交
10

fxy060608's avatar
fxy060608 已提交
11 12 13 14
const V_FOR = 'f'
const V_IF = 'i'
const V_ELSE_IF = 'e'

fxy060608's avatar
init v3  
fxy060608 已提交
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
function isVar (str) {
  if (!str) {
    return false
  }
  const firstLetter = str[0]
  if (
    firstLetter === '"' || // string
    firstLetter === '\'' || // string
    VARS.includes(str) || // boolean | null
    NUMBER_RE.test(str) // number
  ) {
    return false
  }
  return true
}

function addAttr (el, name, value) {
  el.attrsMap[name] = value
  el.attrsList.push({
    name,
    value
  })
}

fxy060608's avatar
fxy060608 已提交
39
function updateEleId (el, it, state) {
fxy060608's avatar
init v3  
fxy060608 已提交
40 41 42 43 44 45 46 47 48
  if (el.type !== 1) {
    return
  }
  const id = el.attrsMap[ID]
  const newId = Number.isInteger(id) ? `("${id}-"+${it})` : `(${id}+${it})`
  addAttr(el, ID, newId)
  const attr = el.attrs.find(attr => attr.name === ID)
  attr.value = newId
  el.children.forEach(child => {
fxy060608's avatar
fxy060608 已提交
49 50 51 52 53 54
    if (!child.for) { // 忽略嵌套 for
      updateEleId(child, it)
    } else {
      child.$parentIterator3 = (child.$parentIterator3 ? (child.$parentIterator3 + '+') : '') + it
      child.forId = `${child.forId}+'-'+${it}`
    }
fxy060608's avatar
init v3  
fxy060608 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  })
}

function getBindingAttr (el, name) {
  return getAndRemoveAttr(el, ':' + name) ||
    getAndRemoveAttr(el, 'v-bind:' + name)
}

function getAndRemoveAttr (el, name) {
  let val
  if ((val = el.attrsMap[name]) != null) {
    const list = el.attrsList
    for (let i = 0, l = list.length; i < l; i++) {
      if (list[i].name === name) {
        list.splice(i, 1)
        break
      }
    }
  }
  delete el.attrsMap[name]
  return val
}

fxy060608's avatar
fxy060608 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
function updateForIterator (el, state) {
  if (!el.for) {
    return
  }
  // 简单处理,确保所有 for 循环,均包含 1,2,3
  const forIteratorId = state.forIteratorId++
  if (!el.iterator1) {
    el.iterator1 = ITERATOR1 + forIteratorId
  }
  if (!el.iterator2) {
    el.iterator2 = ITERATOR2 + forIteratorId
  }
  if (!el.iterator3) {
    el.iterator3 = ITERATOR3 + forIteratorId
  }
}

function updateForEleId (el, state) {
  updateForIterator(el, state)
fxy060608's avatar
init v3  
fxy060608 已提交
97
  if (el.for) {
fxy060608's avatar
fxy060608 已提交
98 99
    const it = el.$parentIterator3 ? (el.$parentIterator3 + '+' + el.iterator3) : el.iterator3
    updateEleId(el, it, state)
fxy060608's avatar
init v3  
fxy060608 已提交
100 101 102 103 104 105 106
  }
}

function getForEl (el) {
  if (el.for) {
    return el
  }
fxy060608's avatar
fxy060608 已提交
107
  if (el.parent && el.parent.for && (el.parent.tag === 'template' || el.parent.tag === 'block')) {
fxy060608's avatar
init v3  
fxy060608 已提交
108 109 110 111 112 113
    return el.parent
  }
}

function processForKey (el) {
  const forEl = getForEl(el)
fxy060608's avatar
fxy060608 已提交
114
  if (forEl && !el.key) { // 占位的 text 标签也无需添加 key
fxy060608's avatar
init v3  
fxy060608 已提交
115 116 117
    if (!isVar(forEl.for)) { // <view v-for="10"></view>
      return
    }
fxy060608's avatar
fxy060608 已提交
118 119
    const it = forEl.iterator3
    if (forEl.tag === 'template' || forEl.tag === 'block') {
fxy060608's avatar
init v3  
fxy060608 已提交
120 121
      if (forEl !== el) {
        const keyIndex = forEl.children.indexOf(el)
fxy060608's avatar
fxy060608 已提交
122
        el.key = `${forEl.forId}+'-${keyIndex}'+${it}`
fxy060608's avatar
init v3  
fxy060608 已提交
123
      } else { // 当 template 下只有文本节点
fxy060608's avatar
fxy060608 已提交
124 125
        if (el.children && el.children.length && !el.children.find(child => child.key)) {
          el.children[0].parent = el
fxy060608's avatar
fxy060608 已提交
126
          el.children[0].key = `${forEl.forId}+'-0'+${it}`
fxy060608's avatar
init v3  
fxy060608 已提交
127 128 129 130
          return true
        }
      }
    } else {
fxy060608's avatar
fxy060608 已提交
131
      el.key = `${forEl.forId}+'-'+${it}`
fxy060608's avatar
init v3  
fxy060608 已提交
132 133 134 135
    }
  }
}

fxy060608's avatar
fxy060608 已提交
136 137 138 139
function hasOwn (obj, key) {
  return hasOwnProperty.call(obj, key)
}

fxy060608's avatar
fxy060608 已提交
140 141 142 143 144 145 146 147 148
function traverseNode (el, parent, state) {
  state.transformNode(el, parent, state)
  el.children && el.children.forEach(child => traverseNode(child, el, state))
  el.ifConditions && el.ifConditions.forEach((con, index) => {
    index !== 0 && traverseNode(con.block, el, state)
  })
  el.scopedSlots && Object.values(el.scopedSlots).forEach(slot => traverseNode(slot, el, state))
}

fxy060608's avatar
init v3  
fxy060608 已提交
149
module.exports = {
fxy060608's avatar
fxy060608 已提交
150 151 152
  V_FOR,
  V_IF,
  V_ELSE_IF,
fxy060608's avatar
fxy060608 已提交
153
  ID,
fxy060608's avatar
fxy060608 已提交
154 155
  SET_DATA,
  GET_DATA,
fxy060608's avatar
init v3  
fxy060608 已提交
156
  isVar,
fxy060608's avatar
fxy060608 已提交
157
  hasOwn,
fxy060608's avatar
init v3  
fxy060608 已提交
158 159 160 161 162
  addAttr,
  getForEl,
  processForKey,
  updateForEleId,
  getBindingAttr,
fxy060608's avatar
fxy060608 已提交
163 164
  getAndRemoveAttr,
  traverseNode
fxy060608's avatar
init v3  
fxy060608 已提交
165
}