parse
processFor用于处理v-for指令:
1 | export function processFor(el: ASTElement) { |
依然还是用例子来帮助理解,假设html为:
1 | <div id="app"> |
首先getAndRemoveAttr看名字应该能查到它是获取并删除特定的节点属性:
1 | // note: this only removes the attr from the Array (attrsList) so that it |
由于我们没有传入removeFromMap参数,所以节点上还是保留了v-for属性。这样我们拿到的exp就是(value,key,index) in items,parseFor用于解析这个表达式,获取其中的各个部分:
1 | export function parseFor(exp: string): ?ForParseResult { |
注释应该很详细,之所以有很多if判断是因为v-for的格式可以有很多种,需要针对性处理。我们的示范经过parseFor处理后拿到结果为:
1 | { |
最终经过parse,上面的这几个属性会全部放到el这个AST节点上。
generate
src/compiler/codegen/index.js中的genFor用于处理AST节点上与v-for相关的属性,生成对应字符串:
1 | export function genFor(el: any, state: CodegenState, altGen?: Function, altHelper?: string): string { |
炒鸡简单有木有,我们生成的字符串如下:
1 | `_l(items, function(value, key, index) { |
_v(createTextVNode)用于创建一个vnode文本结点:
1 | export function createTextVNode(val: string | number) { |
_c在之前讲述vnode时提过,这里再贴出来下:
1 | vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false); |
_l(renderList)用于渲染列表:
1 | /** |
参数val的形式可以有多种:字符串、数字、对象、数组,代码比较简单很快能看懂。
最终我们拿到的render字符串为:
1 | ` |
之后就是生成vnode了,v-for的痕迹就看不到了。