全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-20 10 分钟 ✍️ juanwangdev

编译时指令处理

Vue编译阶段识别并处理 v-if/v-for/v-once 等指令,生成对应的条件渲染、循环渲染和静态优化代码。

v-if 指令处理

AST阶段

JavaScript
function processIf(el) {
  const exp = getAndRemoveAttr(el, 'v-if')
  if (exp) {
    el.if = exp
    addIfCondition(el, { exp, block: el })
  } else {
    if (getAndRemoveAttr(el, 'v-else') != null) {
      el.else = true
    }
    const elseif = getAndRemoveAttr(el, 'v-else-if')
    if (elseif) {
      el.elseif = elseif
    }
  }
}

解析 v-ifv-else-ifv-else,构建条件分支树。

Codegen阶段

JavaScript
function genIf(el, state) {
  el.ifProcessed = true
  return genIfConditions(el.ifConditions, state)
}

function genIfConditions(conditions, state) {
  return conditions.length ?
    conditions.map(cond => {
      if (cond.exp) {
        return `${cond.exp}?${genElement(cond.block, state)}:${genElse()}`
      }
      return genElement(cond.block, state)
    }).join('')
    : '_e()'
}

生成三元表达式链:cond1?render1:cond2?render2:_e()

v-for 指令处理

AST阶段

JavaScript
function processFor(el) {
  let exp = getAndRemoveAttr(el, 'v-for')
  const inMatch = exp.match(forAliasRE)
  if (inMatch) {
    el.for = inMatch[2].trim()  // list | 10
    el.alias = inMatch[1].trim() // item
    // 解构: (item, index)
    const strip = el.alias.replace(stripParenRE, '')
    el.alias1 = strip.split(',')[0].trim()
    el.alias2 = strip.split(',')[1]?.trim()
  }
}

正则解析 v-for="item in list"v-for="(item,i) in list"

Codegen阶段

JavaScript
function genFor(el, state) {
  const exp = el.for
  const alias = el.alias
  const iter = el.alias2 ? `,${el.alias2}` : ''
  
  el.forProcessed = true
  return `_l(${exp},function(${alias}${iter}){` +
    `return ${genElement(el, state)}})`
}

生成 _l(list, function(item, index) { return ... }) 调用。

v-once 指令处理

AST阶段

JavaScript
function processOnce(el) {
  el.once = !!getAndRemoveAttr(el, 'v-once')
}

标记节点为 v-once,后续codegen做静态化处理。

Codegen阶段

JavaScript
function genOnce(el, state) {
  el.onceProcessed = true
  if (el.if && !el.ifProcessed) {
    return genIf(el, state)  // v-if + v-once
  }
  if (el.staticRoot && !el.staticProcessed) {
    return genStatic(el, state)  // 静态根优化
  }
  // 标记并生成一次渲染
  return `_o(${genElement(el, state)},${state.onceId++})`
}

生成 _o(code, id) 调用,渲染时缓存结果。

v-pre 指令处理

JavaScript
function processPre(el) {
  if (getAndRemoveAttr(el, 'v-pre')) {
    el.pre = true
  }
}

// 解析阶段
if (el.pre) {
  inVPre = true  // 跳过后续指令处理
}

// codegen阶段
if (el.pre) {
  // 不处理插值和指令,直接输出原始内容
}

v-pre 跳过模板编译,保留原始模板语法。

指令处理优先级

JavaScript
function genElement(el, state) {
  // 1. 静态根优化
  if (el.staticRoot && !el.staticProcessed) { ... }
  // 2. v-once
  else if (el.once && !el.onceProcessed) { ... }
  // 3. v-if
  else if (el.if && !el.ifProcessed) { ... }
  // 4. v-for
  else if (el.for && !el.forProcessed) { ... }
  // 5. slot
  else if (el.tag === 'slot') { ... }
  // 6. 普通元素
  else { ... }
}

按 staticRoot > v-once > v-if > v-for > slot > 普通元素 优先级处理。

要点总结

  • v-if 生成三元表达式链 cond1?render1:cond2?render2:_e()
  • v-for 解析 item in list(item,index) in list 两种形式
  • v-for 生成 _l(list, function(item, index) { return ... }) 调用
  • v-once 生成 _o(code, id) 调用,渲染时缓存结果
  • v-pre 跳过模板编译,保留原始模板语法
  • 指令处理按 staticRoot > v-once > v-if > v-for > slot > 普通元素 优先级

📝 发现内容有误?点击此处直接编辑

← 上一篇 模板解析与AST生成
下一篇 → 虚拟DOM渲染函数生成
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库