0

0

关于前端模板引擎的问题详解

PHP中文网

PHP中文网

发布时间:2017-06-22 11:03:04

|

1880人浏览过

|

来源于php中文网

原创

 前端模板引擎需要有开发时的透明性

透明性即指我在搭建好开发环境后,随手写代码随手刷新浏览器就能看到最新的效果,而不需要额外地执行任何命令或有任何的等待过程。

所以一切依赖编译过程的模板引擎并不适合前端使用,编译只能是模板引擎的一个特性,而不能是使用的前提

更严格地说,使用FileWatch等手段进行文件变更检测并自动编译也不在我的考虑范围之内,因为这会造成额外的等待,

立即学习前端免费学习笔记(深入)”;

由此可以推出,前端的模板引擎应该是具备可在纯前端环境中解析使用的能力的。

前端模板引擎要有良好的运行时调试能力

由于用户行为的不确定性、执行环境的不确定性、各种第三方脚本的影响等,前端很难做到完全的错误处理和跟踪,这也导致前端必然存在需要直接在线上排查问题的情况

而当问题出现在模板引擎这一层时,就需要模板引擎提供良好的调试能力

一般来说,编译后生成的函数的调试能力是弱于原先手动编写的模板片断的,因为自动生成的函数基本不具备可读性和可断点跟踪性

因此在这一点上,一个供前端使用的模板引擎应该具备在特定情况下从“执行编译后函数获取HTML”换回“解析原模板再执行函数获取HTML”的模式,即应该支持在两种模式间切换

或者更好地,一个强大的前端模板引擎编译生成的函数,可以使用Source Map或其它自定义的手段直接映射回原模板片段,不过现在并没有什么模板引擎实现了这一功能

前端模板引擎要对文件合并友好

在HTTP/2普及之前,文件合并依旧是前端性能优化中的一个重要手段,模板作为文件的一部分,依旧是需要合并的

在提供编译功能的模板引擎中,我们可以使用编译的手段将模板变为JavaScript源码,再在JavaScript的基础上做文件合并

但是如果我们出于上文所说的调试能力等原因希望保留原模板片段,那就需要模板引擎本身支持模板片段合并为一个文件了

大部分仅支持将一段输入的字符串作为模板解析的引擎并不具备这一能力,他们天生并不能将一整个字符串切分为多个模板片段,因而无法支持模板片段层面上的文件合并

需要实现对文件合并的支持,最好的办法就是让模板的语法是基于“片段”的

前端模板引擎要担负XSS的防范

从安全性上来说,前端对XSS的控制是有严格要求的

前端对XSS的防范比较合适的方法是使用“默认转义”的白名单式策略

基于此,一个合理的模板引擎是必须支持默认转义的,即所有数据的输出都默认经过escape的逻辑处理,将关键符号转为对应的HTML实体符号,以从根源上杜绝XSS的入侵路径

当然并不是所有的内容都必须经过转义的,在系统中免不了有对用户输入富文本的需求,因此需要支持特定的语法来产生无转义的输出,但时刻注意无转义输出才是特例,默认情况下必须是转义输出的

前端模板引擎要支持片段的复用

这并不是前端模板引擎的需求,事实上任何模板引擎都应该支持片段的复用,后端如Velocity、Smarty等无不拥有此功能
所谓片段复用,应该有以下几个层次的应用:

  1. 一个片段可以被引入到另一处,相当于一个变量到处用的效果

  2. 一个片段被引入时,可以向其传递不同的数据,相当于一个函数到处用的效果

  3. 一个片段可以被外部替换,但外部不提供此片段的话保持一个默认的内容,类似设计模式中的策略模式

满足第1和第2点的模板引擎并不少,而满足第3点的前端模板引擎却不多见,而后端的Razor、Smarty等都具备这一功能

前端模板引擎要支持数据输出时的处理

所谓数据输出时处理,指一个数据要在输出时做额外的转换,最常见的如字符串的trim操作,比较技术性的如markdown的转换等

诚然数据的转换完全可以在将数据交给模板引擎前就通过JavaScript的逻辑处理完,但这会导致不少有些丑陋又有些冗余的代码,对逻辑本身的复用性也会造成负面的影响

豆包手机助手
豆包手机助手

豆包推出的手机系统服务级AI助手

下载

通常模板引擎对数据做额外处理会使用filter的形式实现,类似bash中的管道的逻辑。filter的实现和注册也会有不同的设计,如mustache其实注册的是fitler工厂,而另一些模板引擎则会直接注册filter本身,不同设计有不同的考量点,我们很难说谁好谁坏 

但是,模板引擎支持数据的输出处理后,会另我们在编码过程中产生一个新的纠结,即哪些数据处理应该交由模板引擎的filter实现,哪些应该在交给模板引擎前由自己的逻辑逻辑实现。这个话题展开来又是一篇长长的论述,于当前的话题无关就略过吧

前端模板引擎要支持动态数据

在开发过程中,其实有不少数据并不是静态的,如EmberJS就提供了Computed Property这样的概念,Angular也有类似的东西,Backbone则可以通过重写Model的get方法来变相实现

虽然ES5在语言层面上直接提供了getter的支持,但我们在前端开发的大部分场景下依旧不会使用这一语言特性,而会选择将动态的数据封装为某种对象的get等方法

而模板引擎在将数据转为HTML片段的过程中,同样应该关注这一点,对这些动态计算的数据有良好的支持

说得更明白一些,模板引擎不应该仅仅接受纯对象(Plain Object)作为输入,而应该更开放地接受类似带有get方法的动态的数据

一个比较合理的逻辑是,如果一个对象有一个get方法(模板引擎决定这个接口),则数据通过该方法获取,其它情况下视输入的对象为纯对象(Plain Object),使用标准的属性获取逻辑

前端模板引擎要与异步流程严密结合

一个很常见的例子是,我们有一个AMD模块存放了全局使用的常量,模板引擎需要使用这些常量。当然我们可以在使用模板引擎之前让JavaScript去异步获取这一模块,随后将常量作为数据传递给模板引擎,但这是一种业务与视图相对耦合的玩法,出于强迫症我并不觉得这是一个漂亮的设计,所以我们希望

  • 模板的输出本身成了异步的方法,而不再像现在一样直接返回字符串

  • 分析模板对异步操作的依赖,整个字符串的拼接逻辑被打断成多个异步

  • 异步是需要等待的,且等待是未知的,从性能上考虑,是否需要考虑Stream式的输出,以便完成一段提供一段

  • 是提供内置的固定几种异步逻辑,还是基于Promise支持任何自定义的异步逻辑,在复杂度和实用性上作出平衡

至今我还没有完全明确模板与异步结合的方式和接口,这个话题也没办法继续深入探讨了

前端模板引擎要支持不同的开发模式

前端发展至今,有很多不同的开发模式,比如:

  • 最普通的HTML页面,使用DOMContentLoaded等事件添加逻辑,特定交互下局部刷新页面

  • 采用传统的MVC模型进行单页式开发

  • 使用MVVM方式以数据为核心,数据与视图方向绑定进行开发

  • 基于Immutable Data进行数据比对Diff转DOM更新的开发(其中可能有Virtual DOM的引入)

一个模板引擎要能支持这么多种不同的的模式是一个非常大的挑战,特别是对双向绑定的支持尤为突出。至今为止几乎所有的支持双向绑定的开发框架都自带了专用的模板引擎,这是因为双向绑定对模板有两大要求:

  • 能够从模板中提取“这一模板对哪些数据有依赖”的元信息

  • 能够知道一个数据变化引擎的是模板的哪一块,而不至于整个刷新

而通用模板引擎很少提供这两个特性,所以没办法对不同的前端开发模式进行全面到位的支持
从模板引擎本身的实现上来说,一种方法是直接将模板解析后的类似AST的结构暴露出去,供其他框架合理地处理,同时提供对模板局部的刷新功能(也可与前面所说的模板片段一起考虑),但是大部分模板引擎为了性能等考虑,是不会解析出类似AST的语法结构来的

前端模板引擎要有实例间的隔离

在大型的前端项目,特别是单页式的项目中,会有完全未知个数的模板片段同时存在,如果这些片段是带有名称(出于复用的考虑)的,就很容易造成名称上的冲突

对于同一层级的逻辑(如大家都是业务层代码,或者大家都是控件层代码),名称冲突是可以通过一些开发时的约定来解决的。但不同层之间,由于封装性的要求,外部不应该知道一些仅内部使用的片段的名称,此时如果不幸有名称与其它层有冲突,会让情况变得比较麻烦,这类问题甚至都不容易跟踪,往往会导致大量的精力和时间的浪费

因此,一个好的模板引擎应该是多实例的,且不同实例间应该相互具备隔离性,不会出现这种不可预期的冲突

将这个话题再往深地研究,就会发现单纯的隔离是不够的,不同层间除了不冲突的需求,同样还有片段复用的需求,我们还会需要不同模板实例间可以开放一些固定的片段共享,因此模板引擎各个实例的关系是一种组合依赖但又具备基本的封装和隔离的状态说了这么多。

相关专题

更多
Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

公务员递补名单公布时间 公务员递补要求
公务员递补名单公布时间 公务员递补要求

公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

44

2026.01.15

公务员调剂条件 2026调剂公告时间
公务员调剂条件 2026调剂公告时间

(一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

58

2026.01.15

国考成绩查询入口 国考分数公布时间2026
国考成绩查询入口 国考分数公布时间2026

笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

11

2026.01.15

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

65

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

75

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

21

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

35

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

【李炎恢】ThinkPHP8.x 后端框架课程
【李炎恢】ThinkPHP8.x 后端框架课程

共50课时 | 4.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号