编译时指令处理
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-if、v-else-if、v-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 > 普通元素 优先级
📝 发现内容有误?点击此处直接编辑