function optimize
function optimize (root: ?ASTElement, options: CompilerOptions) {
if (!root) return
// 函数,用于判断传入参数val是否包含在'type,tag,attrsList,attrsMap,plain,parent,children,attrs,staticClass,staticStyle'
isStaticKey = genStaticKeysCached(options.staticKeys || '')
// 函数,用于判断传入参数val是否是原生html标签或者svg标签
isPlatformReservedTag = options.isReservedTag || no
// first pass: mark all non-static nodes.
markStatic(root)
// second pass: mark static roots.
markStaticRoots(root, false)
}
genStaticKeysCached
function cached<F: Function> (fn: F): F {
// 闭包变量cached用于缓存
const cache = Object.create(null)
return (function cachedFn (str: string) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}: any)
}
// 传入str转为map对象'a,b,c' --> {a: true, b: true, c: true}
// 返回一个方法,用来在map对象中查找是否包含传入属性
function makeMap (
str: string,
expectsLowerCase?: boolean // 是否需要先转化为小写再查找
): (key: string) => true | void {
const map = Object.create(null)
const list: Array<string> = str.split(',')
for (let i = 0; i < list.length; i++) {
map[list[i]] = true
}
return expectsLowerCase
? val => map[val.toLowerCase()]
: val => map[val]
}
// 生成一个方法,传入一个参数val,查看val是否包含在'type,tag,attrsList,attrsMap,plain,parent,children,attrs,staticClass,staticStyle'
genStaticKeysCached = cached(function genStaticKeys (keys: string): Function {
return makeMap(
'type,tag,attrsList,attrsMap,plain,parent,children,attrs' +
(keys ? ',' + keys : '')
)
})
markStatic
function markStatic (node: ASTNode) {
// 判断是否是静态节点
node.static = isStatic(node)
if (node.type === 1) {
if (
!isPlatformReservedTag(node.tag) &&
node.tag !== 'slot' &&
node.attrsMap['inline-template'] == null
) {
return
}
// 遍历children,并标记其是否是静态节点
for (let i = 0, l = node.children.length; i < l; i++) {
const child = node.children[i]
markStatic(child)
// 如果发现子节点非static,则node也是非static
if (!child.static) {
node.static = false
}
}
// 如果包含if表达式,则判断其是否是静态的
if (node.ifConditions) {
for (let i = 1, l = node.ifConditions.length; i < l; i++) {
const block = node.ifConditions[i].block
markStatic(block)
// 如果有一个表达式非static,则node非static
if (!block.static) {
node.static = false
}
}
}
}
}
isStatic
// 文本节点、pre、无动态属性标签和指令的非内建标签将被标记为静态
function isStatic (node: ASTNode): boolean {
// 表达式节点(如插值表达式)
if (node.type === 2) {
return false
}
// 静态文本节点
if (node.type === 3) {
return true
}
return !!(node.pre || (
!node.hasBindings && // 无动态绑定
!node.if && !node.for && // 无 v-if or v-for or v-else
!isBuiltInTag(node.tag) && // 非内建标签,如slot component
isPlatformReservedTag(node.tag) && // 为原生标签,非自定义组件标签
!isDirectChildOfTemplateFor(node) && // 非这种情况:template标签,且该标签包含v-for指令
// node的所有属性都是static的:"type、tag、attrsList、attrsMap、plain、parent、children、attrs、staticClass、staticStyle"
Object.keys(node).every(isStaticKey)
))
}
markStaticRoots
// 标签节点是否为staticRoot
function markStaticRoots (node: ASTNode, isInFor: boolean) {
// 标签节点
if (node.type === 1) {
if (node.static || node.once) {
node.staticInFor = isInFor
}
// 如果node为静态节点,且不只包含一个静态文本节点,则将其标记为staticRoot
if (node.static && node.children.length && !(
node.children.length === 1 &&
node.children[0].type === 3
)) {
node.staticRoot = true
return
} else {
node.staticRoot = false
}
// 遍历node.children,标记其是否为staticRoot
if (node.children) {
for (let i = 0, l = node.children.length; i < l; i++) {
markStaticRoots(node.children[i], isInFor || !!node.for)
}
}
// 遍历if表达式节点,标记其是否为staticRoot
if (node.ifConditions) {
for (let i = 1, l = node.ifConditions.length; i < l; i++) {
markStaticRoots(node.ifConditions[i].block, isInFor)
}
}
}
}
对astElement做了哪些optimize
遍历astElement
- 检测每个element是否是static,并标记element.static
- 检测每个element是否为staticRoot,并标记element.staticRoot