util.js 2.6 KB
Newer Older
fxy060608's avatar
init v3  
fxy060608 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
const VARS = ['true', 'false', 'null']
const NUMBER_RE = /^-?\d*(\.\d+)?$/

const ID = '_i'
const ITERATOR = '$i'
const DATA_ROOT = '$r'

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
  })
}

function updateEleId (el, it) {
  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 => {
    updateEleId(child, it)
  })
}

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
}

function updateForEleId (el) {
  if (el.for) {
    if (!el.iterator1) {
      el.iterator1 = ITERATOR
    }
    updateEleId(el, el.iterator2 || el.iterator1)
  }
}

function getForEl (el) {
  if (el.for) {
    return el
  }
  if (el.parent && el.parent.for && el.parent.tag === 'template') {
    return el.parent
  }
}

function processForKey (el) {
  const forEl = getForEl(el)
  if (forEl && !el.key) {
    if (!isVar(forEl.for)) { // <view v-for="10"></view>
      return
    }
    const it = forEl.iterator2 || forEl.iterator1 || ITERATOR
    if (forEl.tag === 'template') {
      if (forEl !== el) {
        const keyIndex = forEl.children.indexOf(el)
        el.key = `'${forEl.forId}-${keyIndex}-'+${it}`
      } else { // 当 template 下只有文本节点
        if (el.children && el.children.length && !el.children.find(child => child.key)) {
          el.children[0].key = `'${forEl.forId}-0-'+${it}`
          return true
        }
      }
    } else {
      el.key = `'${forEl.forId}-'+${it}`
    }
  }
}

fxy060608's avatar
fxy060608 已提交
107 108 109 110
function hasOwn (obj, key) {
  return hasOwnProperty.call(obj, key)
}

fxy060608's avatar
init v3  
fxy060608 已提交
111 112 113 114 115
module.exports = {
  ID,
  DATA_ROOT,
  ITERATOR,
  isVar,
fxy060608's avatar
fxy060608 已提交
116
  hasOwn,
fxy060608's avatar
init v3  
fxy060608 已提交
117 118 119 120 121
  addAttr,
  getForEl,
  processForKey,
  updateForEleId,
  getBindingAttr,
fxy060608's avatar
fxy060608 已提交
122
  getAndRemoveAttr
fxy060608's avatar
init v3  
fxy060608 已提交
123
}