您的位置:首页 > 其它

Moon系列之slot以及指令相关

2018-01-18 11:23 134 查看

前言

上篇文章中分析了Moon中虚拟DOM的整个逻辑处理,它是Moon整个功能实现的核心,本篇的要说明的slot以及指令的处理都是在上篇文章分析的逻辑过程中,只是上篇文章没有突出说明具体的处理,本篇就是具体的说明Moon是如何处理slot以及指令的。

具体分析

还是通过实例来开始分析整个过程,具体实例代码如下:

<div id="app">
<p m-if="true">{{getToday}}</p>
<mn-test>
<p>{{today}}</p>
<p slot="second">hello world</p>
</mn-test>
</div>
<script src="./moon.js"></script>
<script>
debugger
Moon.component('mn-test', {
template: `<div>
<slot></slot>
<slot name="second"></slot>
</div>`
});
new Moon({
el: '#app',
data: {
today: Date.now()
},
computed: {
getToday: {
get() {
var now = new Date(this.get('today'));
return now.toLocaleString();
}
}
}
});
</script>


上面的实例中涉及到了slot以及指令m-if。

首先整个的过程还是如同虚拟DOM中的处理,需要说明的是m-if在tokens中也是作为标签属性的存在,slot也是作为token中也是作为标签属性的存在。所以在返回render的处理中,lex以及parse中的处理没有什么不同,主要的不同是在于generate中部分。

generate中关于slot以及指令的处理

generate函数的逻辑处理如下:



可以看出slot以及指令是在generateEL函数中处理的。

在具体分析了generateEL函数的处理逻辑,关于slot以及指令的核心逻辑如下:

var compiledCode = "";
// 是否存在插槽slot
if (vnode.type === "slot") {
parentVNode.meta.shouldRender = true;
parentVNode.deep = true;
var slotNameAttr = vnode.props.attrs.name;
compiledCode = 'instance.$slots[\'' + (slotNameAttr && slotNameAttr.value || "default") + '\']';
} else {
// 创建函数体
compiledCode = createCall(vnode, parentVNode);
}

// 虚拟DOM是否存在指令相关的对象
if (vnode.specialDirectivesAfter !== undefined) {
for (var specialDirectiveAfterInfo in vnode.specialDirectivesAfter) {
var specialDirectiveAfter = vnode.specialDirectivesAfter[specialDirectiveAfterInfo];
compiledCode = specialDirectives[specialDirectiveAfter.name].afterGenerate(specialDirectiveAfter.value, specialDirectiveAfter.meta, compiledCode, vnode);
}
}


上面的代码就是generateEL中关于slot以及指令的处理。

上面就说过在lex中生成tokens,上面实例中m-if以及slot都是作为对应标签的属性的,所以就会在createCall中,slot的处理从上面可以直接看出,而对于指令的处理,就要具体分析了。

指令相关

if (vnode.specialDirectivesAfter !== undefined) {
具体代码
}


需要判断虚拟DOM是否存在specialDirectivesAfter对象,通过具体的分析,该对象的添加是在createCall中对于属性的处理,相关处理代码如下:

var attrInfo = attrs[attr];
var specialDirective = null;
// 是否是Moon实例内置的指令
if ((specialDirective = specialDirectives[attrName]) !== undefined) {
if (specialDirective.afterGenerate !== undefined) {
// 添加specialDirectivesAfter对象
if (vnode.specialDirectivesAfter === undefined) {
vnode.specialDirectivesAfter = {};
}
// 指令相关赋值
vnode.specialDirectivesAfter[attr] = attrInfo;
}
if (specialDirective.duringPropGenerate !== undefined) {
generatedObject += specialDirective.duringPropGenerate(attrInfo.value, attrInfo.meta, vnode);
}
vnode.meta.shouldRender = true;
delete attrs[attr];
}


从上面的处理逻辑看出,Moon指令的具有特定的结构,下面就看看m-if的构成:

specialDirectives[Moon.config.prefix + "if"] = {
afterGenerate: function (value, meta, code, vnode) {
return '(' + compileTemplate(value, delimiters, escapedDelimiters, false) + ') ? ' + code + ' : h("#text", ' + generateMeta(defaultMetadata()) + ', "")';
}
};


具体看看compileTemplate的处理逻辑:



compileTemplate的处理结果是:

(true) ? h("p", {attrs: {}}, {"shouldRender": true, "eventListeners": {}}, [h("#text", {"shouldRender": true, "eventListeners": {}}, "" + instance.get("getToday") + "")]) : h("#text", {"shouldRender": false, "eventListeners": {}}, "")


compileTemplate函数还是根据不用的指令处理成不同的render的部分函数体。

对于其他指令,具体的处理我会详细注释,Moon内置的指令都是对象,对象拥有方法beforeGenerate、duringPropGenerate、afterGenerate,这些方法afterGenerate是在generate函数中处理,beforeGenerate和duringPropGenerate是在generateProps中处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: