写点什么

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
用户头像

实时交互,万物互联! 2020.08.10 加入

实时交互,万物互联,全球实时互动云服务商领跑者!

评论

发布
暂无评论
web技术支持| 简单实现Vue第一章:模板编译_Vue_anyRTC开发者_InfoQ写作平台