1
web 技术支持| 简单实现 Vue 第一章:模板编译
作者:anyRTC开发者
- 2022 年 4 月 14 日
本文字数:2344 字
阅读完需:约 8 分钟
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};
复制代码
使用
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./reg.js"></script> <script src="./vue.js"></script>
<style> .box { display: flex; }
img { width: 200px; height: 100%; margin-right: 20px; }
.content { line-height: 27px; font-size: 14px; }
.content span { color: #000; font-weight: 600; } </style></head><body> <div id="app"></div> <script> const template = `<div class='box' style=' width: 900px; height: 300px; border: 1px solid green; margin: 150px auto; padding: 20px; box-sizing: border-box'> <img src='./touxiang.webp'></img> <div class='content'> 您好,我是 <span>{{ name }}</span>,毕业于 <span>{{ university.name }}</span> 大学 <span>{{ university.professional }}</span> 专业。 今天应聘的是贵公司的xxxx岗位。在校期间,我在学校的学生会/团总支/社团/班级/寝室担任xxxx职务。 期间,我参加xxx活动。课余,我还参加了xxxx的实践活动。我的兴趣爱好是xxxx,擅长xxxx。 我对贵公司和xxxx这个岗位十分感兴趣,希望您能给我一个机会。 <br></br> <br></br> 您好,我是 <span>{{ name }}</span>,毕业于 <span>{{ university.name }}</span> 大学 <span>{{ university.professional }}</span> 专业。 今天应聘的是贵公司的xxxx岗位。在校期间,我在学校的学生会/团总支/社团/班级/寝室担任xxxx职务。 期间,我参加xxx活动。课余,我还参加了xxxx的实践活动。我的兴趣爱好是xxxx,擅长xxxx。 我对贵公司和xxxx这个岗位十分感兴趣,希望您能给我一个机会。 </div> </div>`;
const vn = new Vue({ template, data() { return { name: 'Jack', age: 23, university: { name: 'Shanghai Jiao Tong', professional: 'Computer information' } } } }).$mount('app');
console.log(vn); </script></body></html>
复制代码
效果截图
注意:上述代码无法实现以下效果,本章代码只进行了模板编译,还没有渲染真实 DOM;
划线
评论
复制
发布于: 刚刚阅读数: 3
版权声明: 本文为 InfoQ 作者【anyRTC开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/299676a40b0c23c9bda90db8f】。文章转载请联系作者。
anyRTC开发者
关注
实时交互,万物互联! 2020.08.10 加入
实时交互,万物互联,全球实时互动云服务商领跑者!










评论