web技术支持| 简单实现Vue第一章:模板编译
创建vue构造函数
function Vue(option) {
this.$option = option;
}
挂载方法
Vue.prototype.$mount = function(element) {
const rootNode = document.getElementById(element);
if (rootNode) {
this.$rootNode = rootNode;
} else {
throw new Error('$mount Receives an ID node');
}
if (this.$option.template) {
this.$render();
} else {
throw new Error('The lack of the template');
}
return this;
}
Vue.prototype.$render = function render() {
this.$AST = this.$templateCompilation(this.$option.template);
}
Vue.prototype.$templateCompilation = function templateCompilation(html) {
const AST = {
attrs: [],
children: []
};
function start(AST) {
let result = html.match(startReg.startTag);
AST.tagName = result[0];
cuttingHTML(result);
while (html.match(startReg.endTag).index) {
result = html.match(startReg.startAttrs);
AST.attrs.push({
key: result[0].split('=')[0],
value: result[1]
});
cuttingHTML(result);
}
cuttingHTML(html.match(startReg.endTag));
text(AST);
return AST;
}
function text(parent) {
while (html && html.match(textReg.endTag).index) {
let result = html.match(textReg.startTag);
if (result && !result.index) {
parent.children.push(start(JSON.parse(JSON.stringify(AST))));
} else {
result = html.match(textReg.text);
parent.children.push(result[0]);
cuttingHTML(result);
}
}
cuttingHTML(html.match(textReg.endTag));
}
function cuttingHTML(result) {
html = html.substr(result.index + result[0].length);
}
return start(JSON.parse(JSON.stringify(AST)));
}
创建reg.js
const startReg = {
startTag: /[\w\d]+/,
startAttrs: /[^\s=]+\s*=\s*('[^'>]*'|"[^">]*")/,
endTag: /\s*>/
};
const textReg = {
startTag: /\s*<[\w\d]+/,
text: /[^<]+/,
endTag: /\s*<\/[a-z0-9]+>/i
};
使用
Document
效果截图
注意:上述代码无法实现以下效果,本章代码只进行了模板编译,还没有渲染真实DOM;