当前位置: 首页 > article >正文

前端模板引擎

前言

正常渲染拿到数据后渲染,三步走:格式化数据、编译模板、渲染数据
如下例
在这里插入图片描述

  <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>小米商城</title></head><style>* {margin: 0;padding: 0;}body,html {background-color: whitesmoke;font-size: 12px;}ul {list-style: none;}li {display: inline-block;padding: 0 10px;background: white;}h3 {text-align: center;}p {text-align: center;}.title {font-size: 16px;font-weight: 400;color: #333;line-height: 42px;}.desc {color: #b0b0b0;}.price {color: #444;line-height: 58px;}span {color: red;}</style><body><ul id="product-list"><!-- <li><img src="img/1.webp" alt=""><h3 class="title">小米10青春版5G</h3><p class="desc">50倍潜望式驾驶员/轻薄5G手机</p><p class="price"><span>2099</span>元起</p></li><li><img src="img/2.webp" alt=""><h3 class="title">小米10</h3><p class="desc">骁龙865/1亿预期相机</p><p class="price"><span>3799</span>元起</p></li><li><img src="img/3.webp" alt=""><h3 class="title">Redmi K30 Pro</h3><p class="desc">双模5G,骁龙865,投放全面屏</p><p class="price"><span>2699</span>元起</p></li><li><img src="img/4.webp" alt=""><h3 class="title">Redmi K30 Pro准版</h3><p class="desc">双模5G,骁龙865,投放全面屏</p><p class="price"><span>3499</span>元起</p></li> --></ul><script>const productData = {title: '小米手机',list: [{productImgUrl: 'img/1.webp',productCUID: '088722478239',productTitle: 'PTD16-小米10青春版5G',productDesc: '50倍潜望式驾驶员/轻薄5G手机',productPrice: 209000,productCount: 999}, {productImgUrl: 'img/2.webp',productCUID: '088789478639',productTitle: 'PTD16-小米10', //productDesc: '骁龙865/1亿预期相机',productPrice: 379000, //3790.50   一般不会直接传代小数的数字,因为前端的计算是有问题的,一般数据是乘百发送,或者发送字符串自己转换productCount: 999  }, {productImgUrl: 'img/3.webp',productCUID: '088789478339',productTitle: 'PTD16-Redmi K30 Pro',productDesc: '双模5G,骁龙865,投放全面屏',productPrice: 269900,productCount: 0}, {productImgUrl: 'img/4.webp',productCUID: '088789471239',productTitle: 'PTD16-Redmi K30 Pro准版',productDesc: '双模5G,骁龙865,投放全面屏',productPrice: 349900,productCount: 99}]};let oUl = document.querySelector('#product-list');class TempRender {constructor(data = {}, parentEle = '') {this.parentEle = document.querySelector(parentEle);this.originalData = data;this.list = this.formatData(this.originalData.list)this.templateHtml = this.getTemplate(this.data);this.renderHtml();}//格式化数据formatData(list = []) {if (list.length === 0) {return [];}list = list.map(({ productImgUrl, productTitle, productDesc, productPrice }) => {productPrice = productPrice / 100;productTitle = productTitle.replace(/PTD16-/gi, '');productImgUrl = productImgUrl ?? 'img/1.webp'; //?? 是||的进阶版,如果没有值的话设置初始值productTitle = productTitle ?? '暂无信息';productDesc = productDesc ?? '暂无信息';productPrice = productPrice ?? '暂无信息';return {productImgUrl,productTitle,productDesc,productPrice}})return list;}//编译模板getTemplate() {    let template = '';for (let i = 0, len = this.list.length; i < len; i++) {let item = this.list[i];template += ` <li><img src="${item?.productImgUrl }" alt=""><h3 class="title">${item?.productTitle}</h3><p class="desc">${item?.productDesc}</p><p class="price"><span>${item?.productPrice}</span>元起</p></li>`;}return template;}// 渲染数据renderHtml() {this.parentEle.innerHTML += this.templateHtml;}}new TempRender(productData, '#product-list');</script></body></html>

在该业务流程中模板是写死的,变量结构都是写死的,复用性为0,想着把模板当参数传进来,为了效率就借助模板引擎

模板引擎的使用

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>小米商城</title>
</head>
<style>* {margin: 0;padding: 0;}body,html {background-color: whitesmoke;font-size: 12px;}ul {list-style: none;}li {display: inline-block;padding: 0 10px;background: white;}h3 {text-align: center;}p {text-align: center;}.title {font-size: 16px;font-weight: 400;color: #333;line-height: 42px;}.desc {color: #b0b0b0;}.price {color: #444;line-height: 58px;}span {color: red;}
</style><body><ul id="product-list"></ul><script src="js/template-web.js"></script><script type="text/template" id="testTemp"><h1>{{title}}</h1>{{each list}}<li>{{set price = $value.productPrice}}<img src="{{$value.productImgUrl}}" alt=""><h3 class="title">{{$value.productTitle}} {{$index}}</h3><p class="desc">{{$value.productDesc}}</p><p class="price"><span>{{price}}</span>元起</p><!-- <i style="color:red">{{$value.productCount == 0?'无货':'有货'}}</i> -->{{if $value.productCount == 0}}<i style="color:red">无货</i>{{/if}}{{if $value.productCount != 0}}<i style="color:green">有货</i>{{/if}}</li>{{/each}}</script><script>const productData = {title: '小米手机',list: [{productImgUrl: 'img/1.webp',productCUID: '088722478239',productTitle: 'PTD16-小米10青春版5G',productDesc: '50倍潜望式驾驶员/轻薄5G手机',productPrice: 209000,productCount: 999}, {productImgUrl: 'img/2.webp',productCUID: '088789478639',productTitle: 'PTD16-小米10', //productDesc: '骁龙865/1亿预期相机',productPrice: 379000, //3790.50   一般不会直接传代小数的数字,因为前端的计算是有问题的productCount: 999  //一般数据是乘百发送,或者发送字符串自己转换}, {productImgUrl: 'img/3.webp',productCUID: '088789478339',productTitle: 'PTD16-Redmi K30 Pro',productDesc: '双模5G,骁龙865,投放全面屏',productPrice: 269900,productCount: 0}, {productImgUrl: 'img/4.webp',productCUID: '088789471239',productTitle: 'PTD16-Redmi K30 Pro准版',productDesc: '双模5G,骁龙865,投放全面屏',productPrice: 349900,productCount: 99}]};let oUl = document.querySelector('#product-list');let templateHtml = template('testTemp', formatData(productData));oUl.innerHTML = templateHtml;function formatData(data) {let list = data.list;data.list = list.map(({ productImgUrl, productTitle, productDesc, productPrice, productCount }) => {productPrice = productPrice / 100;productTitle = productTitle.replace(/PTD16-/gi, '');productImgUrl = productImgUrl || 'img/1.webp';productTitle = productTitle ?? '暂无信息';productDesc = productDesc || '暂无信息';productPrice = productPrice || '暂无信息';return {productImgUrl,productTitle,productDesc,productPrice,productCount}})return data;}</script>
</body></html>

常见模板工具

jade.js doT.js tpl.js art-template.js handlebars

模板引擎工具的主要用法,就是给数据给模板,然后返回结果.

学习模板引擎主要学习模板引擎的语法

art-template:号称是性能最快的模板引擎

地址: http://aui.github.io/art-template/

handlebars:

地址: https://handlebarsjs.com/

模板语法

模板引擎本质上是通过特定标识符号和语句嵌入HTML文本中 , 通过输入数据 的到 嵌套好数据的HTML文本内容用于生产页面 数据+模板 = 结构内容 , 其中模板语法为核心 下面用art-template语法演示

<ul class="clearfix">{{each target}}<li> 序号: {{$index}} 姓名 :{{$value.name}} 年龄: {{$value.age}}</li>{{/each}}
</ul>

渲染方法

模板工具会提供模板渲染方法, 调用传参 数据 与 模板 返回生成的结构内容结果字符串

 let html = template('testTemp', { target: [{ name: '赫赫', age: 11 }, { name: '豆丁', age: 6 }, { name: '西瓜', age: 5 }, { name: '莉莉莎', age: 8 }, { name: '杰克', age: 22 }, { name: '奥米拉', age: 3 }] })document.body.innerHTML = html;

效果

在这里插入图片描述

在这里插入图片描述

原生模板实现

原理就是正则替换内容

原理步骤:

  1. 正则替换 规定标识符内容

    普通标签

    <%= %> 内容替换成变量的值

    <% %> 内容替换成js代码

  2. 动态生成渲染函数 new Function(函数字符串)

  3. 通过正则格式化模板内容

  4. 拼接返回格式化模板内容代码字符串

<!DOCTYPE html>
<html lang="zh-cn"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>商品</title>
</head><body><script type="text/template" id="temp"><h2><%= data.title %></h2><ul><% for(let i=0; i < data.list.length; i++) { %><li data-index=<%=i%>><%= data.list[i] %><% if(data.list[i].length>3) {%><%= '哈哈哈' %><% } %> </li><% } %></ul></script><script>function getTempScript(id) {let script = document.querySelector(`#${id}[type="text/template"]`); return `${script.innerHTML}`}function compile(id) {let template = getTempScript(id);let evalExp = /<%=(.+?)%>/g,expr = /<%([\s\S]+?)%>/g;template = template.replace(evalExp, '`) \n echo($1) \n echo(`').replace(expr, '`) \n $1 \n echo(`');template = 'echo(`'+template +'`)';let funcStr = `let html = '';function echo(content) {html += content;}${template}return html;`return funcStr;}let funStr = compile('temp');let comp1 = new Function('data',funStr);document.body.innerHTML += comp1({ title: '标题', list: ['糖醋鱼', '香辣蟹', '红烧排骨'] })</script>
</body></html>

相关文章:

前端模板引擎

前言 正常渲染拿到数据后渲染&#xff0c;三步走&#xff1a;格式化数据、编译模板、渲染数据 如下例 <!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice…...

Linux /dev/null

/dev/null 是 Linux 和类 Unix 系统中一个特殊且非常有用的设备文件&#xff0c;也被称为空设备。下面为你详细介绍它的特点、用途和使用示例。 特点 写入丢弃&#xff1a;当向 /dev/null 写入数据时&#xff0c;这些数据会被立即丢弃&#xff0c;不会被保存到任何地方&#…...

ubuntu安装docker 无法拉取问题

sudo docker run hello-world [sudo] ubuntu 的密码&#xff1a; Unable to find image hello-world:latest locally docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded (Client.Timeout exceeded while awai…...

深入理解Kubernetes:容器编排的中流砥柱

Kubernetes容器编排 在云原生技术蓬勃发展的当下&#xff0c;Kubernetes&#xff08;简称K8s&#xff09;已成为容器编排领域的事实标准&#xff0c;为现代应用的部署、管理与扩展提供了强大支持。 K8s的核心优势之一是其卓越的容器编排能力 在传统应用部署模式下&#xff0c;…...

长尾词SEO优化软件:企业官网流量提升的软件【实测】

搜索引擎流量中68%来自长尾关键词&#xff08;数据来源&#xff1a;Ahrefs 2025&#xff09;&#xff0c;但83%企业仍困于「高价值长尾词难挖掘内容生产跟不上」的双重困境。当同行用智能工具批量布局「孕妇防辐射服哪个牌子好」等精准词时&#xff0c;手动分析数据的你可能还在…...

用自己的数据训练yolov11目标检测

文章目录 概要理论知识整体架构流程架构优化多任务支持多参数体量 操作实操环境配置数据准备数据标注数据放置路径 训练预测 概要 YOLOv11 是 Ultralytics 团队于 2024 年 9 月 30 日发布的最新目标检测模型&#xff0c;延续了 YOLO 系列实时推理特性&#xff0c;同时通过架构优…...

gsoap实现webservice服务

gsoap实现webservice服务 在实现Web服务时&#xff0c;使用gSOAP是一个很好的选择&#xff0c;因为它提供了强大的工具和库来创建SOAP和RESTful服务。gSOAP是一个C和C语言开发的库&#xff0c;它支持SOAP协议的各种版本&#xff0c;包括SOAP 1.1和SOAP 1.2。下面是如何使用gSO…...

相比于WebSocket,SSE更适合轻量级

一、 前言 项目首页有一个待办任务数量和消息提醒数量的展示&#xff08;单向数据的展示 &#xff09;&#xff0c;之前使用了定时器&#xff0c;每隔十秒钟发送一次请求到后端接口拿数据&#xff0c;这也就是我们常说的轮询做法。 1. 轮询的缺点 我们都知道轮询的缺点有几种…...

项目2 数据可视化--- 第十五章 生成数据

数据分析是使用代码来探索数据内的规律和关联。 数据可视化是通过可视化表示来 探索和呈现数据集内的规律。 好的数据可视化&#xff0c;可以发现数据集中未知的规律和意义。 一个流行的工具是Matplotlib&#xff0c;他是一个数据绘图库&#xff1b; 还有Plotly包&#xff…...

【Maven私服配置】

Maven私服配置 对于一些中央的pom&#xff0c;应该配置对应的mirror镜像访问 <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirr…...

QT (四)模型/视图 QFileSystemModel,QStringListModel,QStandardItemModel

思考&#xff1a;QTableWidget 在某种程度上可以等价为QStandardItemModel&#xff0c;同理&#xff0c;其他的功能也有类似的等价&#xff0c;但是以当前的QTableWidget 和QStandardItemModel为例的话&#xff0c;两者都是用于实现建立表格的相关组件&#xff0c;只不过QStand…...

BSD实现:单播

分用单播数据报 如果程序执行到这里&#xff0c;说明程序并没有执行多播操作&#xff0c;那么大概率是单播。 维护缓存指针 udp_last_inpcb是上一次接收数据报的端口的控制块指针&#xff0c;维护该指针的依据是许多程序往往具有时间局部性&#xff0c;也就是&#xff1a;经…...

. Unable to find a @SpringBootConfiguration(默认软件包中的 Spring Boot 应用程序)

解决&#xff1a; 新建一个包即可 问题&#xff1a; 默认软件包中的 Spring Boot 应用程序。 原因&#xff1a; 默认包的定义 &#xff1a; 如果一个 Java 类没有使用 package 声明包名&#xff0c;则该类会被放置在默认包中。Spring Boot 遵循 Java 的包管理约定&#xff…...

【前端知识】浏览器兼容方案polyfill

浏览器兼容方案polyfill 什么是 Polyfill&#xff1f;Polyfill 的作用Polyfill 的工作原理1. **特性检测**2. **加载 Polyfill**3. **模拟实现** Polyfill 的常见场景Polyfill 的使用方式Polyfill 的优缺点优点缺点 常见的 Polyfill 库总结 什么是 Polyfill&#xff1f; Polyf…...

互信息的定义与公式

互信息 定义公式 从条件熵中我们知道&#xff0c;当获取的信息和要研究的食物”有关系时“&#xff0c;这些信息才能帮助我们消除不确定性。如何衡量获取信息和要研究事物“有关系”呢&#xff1f;比如常识告诉我们&#xff0c;一个随机事件“今天深圳下雨”和另一个随机事件“…...

(算法基础——树)——python树结构使用指南

1. 树的定义与实现 树是一种非线性数据结构&#xff0c;常用于解决层次化数据问题&#xff08;如路径搜索、二叉树遍历等&#xff09;。以下是树的两种常见实现方式&#xff1a; (1) 类&#xff08;Class&#xff09;实现 class TreeNode:def __init__(self, val0, leftNone…...

【小白学AI系列】NLP 核心知识点(七)Embedding概念介绍

Embedding&#xff08;嵌入&#xff09; 是自然语言处理&#xff08;NLP&#xff09;中非常重要的概念。简单来说&#xff0c;embedding 是一种将离散的、稀疏的、不可直接计算的对象&#xff08;比如词、字符或句子&#xff09;转换为 密集的、连续的向量表示 的技术。 这个向…...

Android adb测试常用命令大全

目录 一、查看最上层成activity名字: 二、查看Activity的任务栈&#xff1a; 三、获取安装包信息 四、性能相关 1、显示CPU信息 : 2、查看CPU使用信息 3、内存信息&#xff08;meminfo package_name or pid 使用程序的包名或者进程id显示内存信息&#xff09; 4、电量信…...

FRRouting配置与OSPF介绍,配置,命令,bfd算法:

文章目录 1、frrouting的配置&#xff1a;2、ospf2.1、检测和维护邻居关系2.2、ospfDR和BDR2.3、odpf邻居表2.4、ospf常用命令2.5、bfd配置 1、frrouting的配置&#xff1a; sudo service zebra start sudo service ospfd start telnet localhost 2604 en configure termina…...

【MyBatis】预编译SQL与即时SQL

目录 1. 以基本类型参数为例测试#{ }与${ }传递参数的区别 1.1 参数为Integer类型 1.2 参数为String类型 2. 使用#{ }传参存在的问题 2.1 参数为排序方式 2.2 模糊查询 3. 使用${ }传参存在的问题 3.1 SQL注入 3.2 对比#{ } 与 ${ }在SQL注入方面存在的问题 3.3 预编译…...

prometheus、grafana、windows、node exporter 安装包

开发过程中应用到的安装包软件&#xff1a; prometheus-2.20.0.windows-amd64.tar.gz windows_exporter-0.13.0-amd64.exe grafanawindows-x64.zip influxdb-1.7.0_windows_amd64.zip 我用夸克网盘分享了「prometheus、grafana、windows、node exporter 安装包」&#xff…...

Python数据可视化 - Matplotlib教程

文章目录 前言一、Matplotlib简介及安装1. Matplotlib简介2. 安装Matplotlib 二、Matplotlib Pyplot1. Pyplot介绍2. Pyplot中方法介绍2.1 创建和管理图形2.2 绘制图形2.3 设置图形属性2.4 保存和展示 三、Matplotlib绘图标记1. 介绍2. 基本用法3. 标记大小与颜色4. 标记样式列…...

DeepSeek R1 与 OpenAI O1:机器学习模型的巅峰对决

我的个人主页 我的专栏&#xff1a;人工智能领域、java-数据结构、Javase、C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞&#x1f44d;收藏❤ 一、引言 在机器学习的广袤天地中&#xff0c;大型语言模型&#xff08;LLM&#xff09;无疑是最…...

内容中台重构企业内容管理流程驱动智能协作升级

内容概要 内容中台作为企业数字化转型的核心基础设施&#xff0c;通过技术架构革新与功能模块整合&#xff0c;重构了传统内容管理流程的底层逻辑。其核心价值在于构建动态化、智能化的内容生产与流转体系&#xff0c;将分散的创作、存储、审核及分发环节纳入统一平台管理。基…...

STM32 Flash详解教程文章

目录 Flash基本概念理解 Flash编程接口FPEC Flash擦除/写入流程图 Flash选项字节基本概念理解 Flash电子签名 函数读取地址下存放的数据 Flash的数据处理限制部分 编写不易&#xff0c;请勿搬运&#xff0c;感谢理解&#xff01;&#xff01;&#xff01; Flash基本概念…...

小米 R3G 路由器刷机教程(Pandavan)

小米 R3G 路由器刷机教程&#xff08;Pandavan&#xff09; 一、前言 小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而&#xff0c;原厂固件的功能相对有限&#xff0c;难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能&#xff0c;还能通过第三方固…...

红队视角出发的k8s敏感信息收集——Kubernetes API 扩展与未授权访问

针对 Kubernetes API 扩展与未授权访问 的详细攻击视角分析&#xff0c;聚焦 Custom Resource Definitions (CRD) 和 Aggregated API Servers 的潜在攻击面及利用方法&#xff1a; ​ 攻击链示例 1. 攻击者通过 ServiceAccount Token 访问集群 → 2. 枚举 CRD 发现数据库配…...

11. Docker 微服务实战(将项目打包生成镜像,在 Docker 当中作为容器实例运行)

11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行) 文章目录 11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行)2. 最后&#xff1a; 建 Module - docker_boot 编辑 pom <?xml version"1.0&…...

mysql和minio

在现代应用架构中&#xff0c;Word 文档、PPT 等文件通常存储在对象存储服务&#xff08;如 MinIO&#xff09;中&#xff0c;而不是直接存储在关系型数据库&#xff08;如 MySQL&#xff09;中。以下是具体的分工和原因&#xff1a; 为什么选择对象存储&#xff08;如 MinIO&a…...

计算机视觉:卷积神经网络(CNN)基本概念(二)

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络 接上一篇《计算机视觉&am…...