Preface
In the last article, the whole logic processing of virtual DOM in Moon is analyzed. It is the core of the whole function realization of Moon. The slot and instruction processing in this article are all in the logic process of the analysis in the previous article, but the specific processing is not highlighted in the previous article. This article is a specific description of how Moon handles slots and instructions.
make a concrete analysis
Or through examples to start the analysis of the whole process, the specific example code is as follows:
<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>
The above example involves slot and instruction m-if.
First of all, the whole process is just like the processing in virtual DOM. It needs to be explained that m-if exists as tag attribute in tokens, slot also exists as tag attribute in token. So in the process of returning render, the processing in lex and parse is not different, the main difference is in the part of generate.
Processing of slot s and instructions in generation
The logic of the generate function is as follows:
You can see that slot s and instructions are processed in the generateEL function.
The processing logic of generateEL function is analyzed concretely. The core logic of slot and instruction is as follows:
var compiledCode = "";
// Is there a 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 {
// Creating Function Body
compiledCode = createCall(vnode, parentVNode);
}
// Does the Virtual DOM Have Instruction-Related Objects
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);
}
}
The above code is the processing of slot s and instructions in generateEL.
As mentioned above, tokens are generated in lex. m-if and slot in the example above are attributes of corresponding tags. So in createCall, slot processing can be seen directly from above, while instruction processing should be analyzed in detail.
Instruction correlation
if (vnode.specialDirectivesAfter !== undefined) { Specific code }
It is necessary to determine whether there is a special DirectivesAfter object in virtual DOM. Through specific analysis, the addition of this object is the processing of attributes in createCall. The relevant processing code is as follows:
var attrInfo = attrs[attr];
var specialDirective = null;
// Are they built-in instructions for Moon instances?
if ((specialDirective = specialDirectives[attrName]) !== undefined) {
if (specialDirective.afterGenerate !== undefined) {
// Add the specialDirectivesAfter object
if (vnode.specialDirectivesAfter === undefined) {
vnode.specialDirectivesAfter = {};
}
// Instruction-related assignment
vnode.specialDirectivesAfter[attr] = attrInfo;
}
if (specialDirective.duringPropGenerate !== undefined) {
generatedObject += specialDirective.duringPropGenerate(attrInfo.value, attrInfo.meta, vnode);
}
vnode.meta.shouldRender = true;
delete attrs[attr];
}
From the above processing logic, Moon instruction has a specific structure. Let's look at the composition of m-if.
specialDirectives[Moon.config.prefix + "if"] = {
afterGenerate: function (value, meta, code, vnode) {
return '(' + compileTemplate(value, delimiters, escapedDelimiters, false) + ') ? ' + code + ' : h("#text", ' + generateMeta(defaultMetadata()) + ', "")';
}
};
Look specifically at the processing logic of compileTemplate:
The result of compileTemplate processing is:
(true) ? h("p", {attrs: {}}, {"shouldRender": true, "eventListeners": {}}, [h("#text", {"shouldRender": true, "eventListeners": {}}, "" + instance.get("getToday") + "")]) : h("#text", {"shouldRender": false, "eventListeners": {}}, "")
The compileTemplate function is also handled as part of a different render function body according to unused instructions.
For other instructions, I will comment on the specific processing. Moon's built-in instructions are all objects. Objects have methods beforeGenerate, duringPropGenerate, afterGenerate. These methods are processed in generation function, beforeGenerate and duringPropGenerate are processed in generate Props.