/** ?* 模板引擎 ?* @param {*} option? ?*/ function JRazor(option) { ? ? this.settings = { ? ? ? ? razor: '`', ? ? ? ? ? ? ? ? ? ? //标记js代码的字符 ? ? ? ? razorEncodeChar: '´', ? ? //标记js代码的字符的转义字符 ? ? ? ? openLog:true ? ? ? ? ? ? ? ? ? ?//是否在控制台输出预编译日志 ? ? } ? ? if (option) { ? ? ? ? if (option.razor !== undefined) { ? ? ? ? ? ? this.settings.razor = option.razor; ? ? ? ? } ? ? ? ? if (option.razorEncodeChar !== undefined) { ? ? ? ? ? ? this.settings.razorEncodeChar = option.razorEncodeChar; ? ? ? ? } ? ? ? ? if(option.openLog!==undefined){ ? ? ? ? ? ? this.settings.openLog=option.openLog; ? ? ? ? } ? ? }
? ? /** ? ? ?* 执行模板引擎 ? ? ?* @param {HTMLBaseElement} template 模板元素 ? ? ?* @param {*} model 数据模型 ? ? ?*/ ? ? this.execute = function (template, model) { ? ? ? ? let templateText = template.innerHTML; ? ? ?//模板中的文本 ? ? ? ? let codeArray = templateText.split("\n"); ? //用换行符分割的代码数组 ? ? ? ? let compiledCode = "let _html='';\n"; ? ? ? //预编译的代码 ? ? ? ? for (let i = 0; i < codeArray.length; i++) { ? ? ? ? ? ? let item = codeArray[i]; ? ? ? ? ? ? let itemTrim = item.trim(); ? ? ? ? ? ? if (itemTrim.startsWith(this.settings.razor)) { ? ? ? ? ? ? ? ? compiledCode += itemTrim.substr(1) + "\n"; ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? compiledCode += "_html+=`" + item + "`\n"; ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? compiledCode = compiledCode.replace(/</g, "<"); ?//还原转义的小于号 ? ? ? ? compiledCode = compiledCode.replace(/>/g, ">"); ?//还原转义后的大于号 ? ? ? ? compiledCode = compiledCode.replace(new RegExp(this.settings.razorEncodeChar,"g"), this.settings.razor);//还原转义后的胡须 ? ? ? ? compiledCode += "template.insertAdjacentHTML('beforebegin',_html);\n"; ? ? ? ? compiledCode += "template.remove();"; ? ? ? ? if(this.settings.openLog){ ? ? ? ? ? ? let log="function __execute__(template,model){\n"; ? ? ? ? ? ? log+=compiledCode; ? ? ? ? ? ? log+="\n}" ? ? ? ? ? ? console.log(log); ? ? ? ? } ? ? ? ? const __execute__ = new Function("template", "model", compiledCode); ? ? ? ? __execute__(template, model); ? ? } }
<!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> ? ? <style type="text/css"> ? ? ? ? table { ? ? ? ? ? ? width: 500px; ? ? ? ? ? ? border-collapse: collapse; ? ? ? ? }
? ? ? ? th, ? ? ? ? td { ? ? ? ? ? ? border: 1px solid #000; ? ? ? ? ? ? padding: 3px; ? ? ? ? } ? ? </style> </head>
<body> ? ? <script type="text/template" id="template1"> ? ? ? ? <!-- 这一行是html注释,与标准html注释没有区别 --> ? ? ? ? `//这是javascript注释,第一个`号代表此行将被解析为javascript,紧随其后的//或/**为常规的javascript注释
? ? ? ? `/** ? ? ? ? `JRazor方法论: ? ? ? ? `工具集成: ? ? ? ? ` ? ?JRazor充分照顾主流的开发工具,如代码的高亮、结构校验、快捷键等。 ? ? ? ? `关于轮子: ? ? ? ? ` ? ?没本事造轮子的人才说不要重复造轮子。 ? ? ? ? `两种视角: ? ? ? ? ` ? ?框架视角:JRazor的本质是javascript,模板中的每一行(包括注释和空行)都将被预编译为javascript代码,您可以在浏览器控制台看到预编译好的代码; ? ? ? ? ` ? ?开发视角:JRazor是一个HTML片段,因此JRazor优先照顾HTML代码的原汁原味。 ? ? ? ? `我的纠结: ? ? ? ? ` ? ?JRazor将按行解析模板的内容,以反引号`(或构造函数声明的其他符号)开始的行将被解析为javascript,以其他字符开始的行将被解析为html; ? ? ? ? ` ? ?牢记"按行解析"四个字很重要,您的一行代码中一定不能既有html又有javascript; ? ? ? ? ` ? ?之所以按行解析,而不使用正则解析,是在性能、核心代码量、可读性综合权衡后所作出的选择。 ? ? ? ? `前端福祉: ? ? ? ? ` ? ?`${}`是es6给前端工程师带来的最有诚意的礼物, ? ? ? ? ` ? ?您在编写JRazor模板代码时应充分利用`${}`,任何说明性的文字都不如您亲自打开控制台看看预编译好的代码是如何工作的。 ? ? ? ? `关于源码: ? ? ? ? ` ? ?如果您打开jrazor.js文件后发出“什么鬼,这叫框架?”的感叹, ? ? ? ? ` ? ?那么作者会很欣慰,没错,这就是一个将近40岁的老头子搞出来的东西,100行不到的代码就是JRazor的全貌; ? ? ? ? `帮助文档: ? ? ? ? ` ? ?我还能说什么呢?祝您工作愉快,全家美满!用JRazor,长头发,奥利给! ? ? ? ? `*/ ? ? <table style="background-color: #fff;"> ? ? ? ? <tr> ? ? ? ? ? ? <th colspan="4">${model.title}</th> ? ? ? ? </tr> ? ? ? ? <tr> ? ? ? ? ? ? <th colspan="2">宠物</th> ? ? ? ? </tr> ? ? ? ? <tr> ? ? ? ? ? ? <th>名称</th> ? ? ? ? ? ? <th>颜色</th> ? ? ? ? </tr> ? ? ? ? `model.animals.forEach(function(item){ ? ? ? ? `//建议使用forEach或for in 会使代码看起来更干净 ? ? ? ? <tr> ? ? ? ? ? ? <td>${item.name}</td> ? ? ? ? ? ? <td style="background-color:${item.color};">${item.color}</td> ? ? ? ? </tr> ? ? ? ? `}) ? ? ? ? <tr> ? ? ? ? ? ? <th colspan="2">衣服</th> ? ? ? ? </tr> ? ? ? ? <tr> ? ? ? ? ? ? <th>名称</th> ? ? ? ? ? ? <th>价格</th> ? ? ? ? </tr> ? ? ? ? `for(let i=0;i<model.clothes.length;i++){ ? ? ? ? `var item=model.clothes[i]; ? ? ? ? <tr> ? ? ? ? ? ? <td>${item.name}</td> ? ? ? ? ? ? `//以下演示if else 和 三元运算符 ? ? ? ? ? ? `if(item.price<200){ ? ? ? ? ? ? <td style="background-color:${item.price<200?'green':'red'};">低</td> ? ? ? ? ? ? `}else{ ? ? ? ? ? ? <td style="background-color:${item.price<200?'green':'red'};">高</td> ? ? ? ? ? ? `} ? ? ? ? </tr> ? ? ? ? `} ? ? </table> ? ? </script> ? ? <script type="text/javascript" src="jrazor.js"></script> ? ? <script type="text/javascript"> ? ? ? ? const api = { ? ? ? ? ? ? title: "用JRazor,长头发,奥利给!", ? ? ? ? ? ? animals: [ ? ? ? ? ? ? ? ? { name: "狗狗", color: "red" }, ? ? ? ? ? ? ? ? { name: "猫子", color: "gray" }, ? ? ? ? ? ? ? ? { name: "小鸟", color: "green" } ? ? ? ? ? ? ], ? ? ? ? ? ? clothes: [ ? ? ? ? ? ? ? ? { name: "衬衫", price: "120" }, ? ? ? ? ? ? ? ? { name: "西服", price: "620" }, ? ? ? ? ? ? ? ? { name: "裤子", price: "300" }, ? ? ? ? ? ? ] ? ? ? ? }
? ? ? ? //通常使用无参的构造函数即可,以下仅为体现构造函数参数的全貌 ? ? ? ? const razor = new JRazor({ ? ? ? ? ? ? razor: '`', ? ? ? ? ? ? ? ? ? ? ? //标记js代码的字符,默认值:` ? ? ? ? ? ? razorEncodeChar: '´', ? ? ? //标记js代码的字符的转义字符,默认值:´ ? ? ? ? ? ? openLog:true ? ? ? ? ? ? ? ? ? ? ?//是否在控制台输出预编译日志,默认值:true ? ? ? ? });
? ? ? ? razor.execute(document.getElementById("template1"), api); ? ? </script> </body>
</html>
源代码地址:JRazor: 极简约的前端模板语言。 (gitee.com)
|