前端模板引擎

news2025/3/31 19:55:22

前言

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

  <!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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2300092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

长尾词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…

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

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

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

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

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

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

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 预编译…

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&…

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

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

【数据结构-红黑树】

文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff08;Binary Search Tree, BST&#xff09;&…

dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型

要将 dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型. 申请阿里云百练的KEY 添加模型 测试模型

应用分层、三层架构和MVC架构

前言 在前面中&#xff0c;我们已经学习了Spring MVC 的一些基础操作&#xff0c;那么后面就用一些简单的案例来巩固一下。 在开始学习做案例之前&#xff0c;我们先来了解一下在软件开发中常见的设计模式和架构。 应用分层 含义 应用分层是一种软件开发设计思想&#xff0…

Apache Struts2 - 任意文件上传漏洞 - CVE-2024-53677

0x01&#xff1a;漏洞简介 Apache Struts 是美国 Apache 基金会的一个开源项目&#xff0c;是一套用于创建企业级 Java Web 应用的开源 MVC 框架&#xff08;将软件分为模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&a…