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
的痕迹就看不到了。