JRazor--史上最简单性能最强的HTML模板引擎
javascript代码如下:
/**
* 模板引擎
* @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);
}
}
html代码如下:
<!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)
相关推荐
Cherry-Studio-CN-2.1.6-win-x64-setup.exe
Cherry-Studio-CN-2.1.6-win-x64-setup.exe
【高速电路设计】基于协议的板级布局指南:差分信号完整性与电源热管理协同优化方案
内容概要:本文档详细介绍了规格补充学习,并在实际项目中配合仿真工具与实测手段进行验证。
《AutoCAD 机械工程基础教程2014版》课件+教案+教学大纲
《AutoCAD 机械工程基础教程2014版》课件+教案+教学大纲
国央企创新负责人如何借助平台实现创新资源的高效协同配置?.docx
科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。
基于小波分析的小电流接地系统单相接地故障选线仿真【仿真+说明文档+说明PPT】
基于小波分析的小电流接地系统单相接地故障选线仿真【仿真+说明文档+说明PPT】内容概要:本文围绕一个多机器人路径规划(Multi-Agent Path Finding, MAPF)的MATLAB代码库进行系统性解读,重点阐述了基于优先级规划(Prioritized Planning, PP)的求解框架。该框架采用四层架构设计——几何解析、拓扑构建、调度规划与可视化呈现,实现了从地图输入到无冲突路径输出的完整流程。核心技术包括动态边权膨胀机制以缓解硬封锁带来的不可解问题、节点预留历史结构提升冲突查询效率、几何惩罚驱动的局部同步策略降低时间复杂度,以及基于Petri网的两阶段整数规划方法用于判定解的存在性与优化路径序列。文章还详细分析了三种时间同步策略的取舍、交换冲突的处理机制及可视化链路的设计实现,强调了工程实践中信息前移、模块解耦与可维护性的重要性。; 适合人群:具备一定算法基础和MATLAB编程能力,从事路径规划、多智能体系统、机器人调度等相关领域的科研人员与研究生。; 使用场景及目标:① 学习和复现多机器人路径规划中的优先级规划算法及其工程实现;② 理解动态边权膨胀、节点预留、局部同步等关键技术如何提升算法效率与鲁棒性;③ 借鉴模块化框架设计思想,应用于仓储物流、无人机编队、自动驾驶等实际场景的路径规划系统开发;④ 利用提供的可视化工具进行算法行为分析与教学演示。; 阅读建议:建议读者按照文中所述的数据流顺序逐步研读各模块,重点关注各层之间的接口设计与不变量约束,结合代码实践调试不同地图与智能体规模下的运行效果,并尝试调整惩罚权重、同步策略等参数以深入理解算法性能边界。


