https://www.zhihu.com/question/32524504
我对题主的问题有些意见。
首先,jQuery.tmpl 是一个插件,jQuery 本身跟模板毫无关系。Backbone 所谓的 template 功能是 underscore 里面的一个函数,是可替换的,你手动拼接 html 字符串也可以,说是 underscore template 更准确一点(其实原版还是 John Resig 写的)。
其次,我很反对把 Angular React 这样的东西和模板引擎混为一谈。“前端框架” 和 “模板引擎” 是两个概念。我看到有人把所有的框架都笼统的叫做模板引擎,就像看到有人把 HTML5 叫成 H5 一样不舒服。我们可以说 Angular 有针对模板的处理策略,但它无论是理念、实现和使用方式和通常所说的模板引擎都是完全不一样的,所包含的功能也远远超过模板引擎的范畴。React 就更不一样了,因为丫根本就没有模板的概念。
严格的模板引擎的定义,输入模板字符串 + 数据,得到渲染过的字符串。实现上,从正则替换到拼 function 字符串到正经的 AST 解析各种各样,但从定义上来说都是差不多的。字符串渲染的性能其实也就在后端比较有意义,毕竟每一次渲染都是在消耗服务器资源,但在前端,用户只有一个,几十毫秒的渲染时间跟请求延迟比起来根本不算瓶颈。倒是前端的后续更新是字符串模板引擎的软肋,因为用渲染出来的字符串整个替换 innerHTML 是一个效率很低的更新方式。所以这样的模板引擎如今在纯前端情境下已经不再是好的选择,意义更多是在于方便前后端共用模板。
相比之下 Angular 是 DOM-based templating,直接解析 live DOM 来提取绑定,如果是字符串模板则是先转化成 live DOM 再解析。数据更新的时候直接通过绑定做局部更新。其他 MVVM 如 Knockout, Vue, Avalon 同理。缺点是没有现成的服务端渲染,要做服务端渲染基本等于重写一个字符串模板引擎。不过其实也不难,因为 DOM-based 的模板都是合法的 HTML,直接用现成的 HTML parser 预处理一下,后面的工作就相对简单了。
框架里面也有在前端解析字符串模板到静态 AST 再生成 live DOM 做局部更新的,比如 Ractive 和
的 Regular。这一类的实现因为解析到 AST 的这步已经在框架内部完成了,所以做服务端渲染几乎是现成的,另外也可以在构建时进行预编译。
然后说说 React,JSX 根本就不是模板,它就是带语法糖的手写 AST,并且把语法糖的处理放到了构建阶段。因为运行时不需要解析,所以 virtual DOM 可以每次渲染都重新生成整个 AST,在客户端用 diff + patch,在服务端则直接 serialize 成字符串。所有其他 virtual DOM 类方案同理。像 virtual-dom,mithril 之类的连语法糖都不带。
最后说下我的看法:如果是静态内容为主,那就直接服务端渲染好了,首屏加载速度快。如果是动态的应用界面,那就不应该用拼模板的思路去做,而是用做应用的架构(MV*,组件树)思路去做。链接:https://www.zhihu.com/question/32524504/answer/55740503
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
模板引擎有很多,比较知名的在各回答里也都提及了,而我要说的是一个更根本的问题,怎么样的模板引擎是适合前端的
首先说明一点,underscore.template这种东西不叫模板引擎,他还不够格来配上“引擎”这两个字,充其量就是一个模板函数,因此不会在这个回答的探讨范围里
由于这个推理的过程相当冗长,基本是用好几年的实际经验和踩过无数坑后堆出来的,别的不说光我们团队自己用的模板引擎都前后有3个版本,现在我正在思考第4个版本应该有的特性(某实现者已吐血),可见我们对此的思考从来没有停止。所以这边只说一些结论性的东西,一个前端的模板引擎需要有怎么样的特性
以下特性没有特定的排序,不分先后,纯粹想到一条写一条出来,也作为工作到现阶段在模板引擎这一话题上的总结吧
前端模板引擎需要有开发时的透明性
我认为前端任何框架和工具都要有对开发的透明性,模板引擎也不例外。所谓透明性即指我在搭建好开发环境后,随手写代码随手刷新浏览器就能看到最新的效果,而不需要额外地执行任何命令或有任何的等待过程
所以一切依赖编译过程的模板引擎并不适合前端使用,编译只能是模板引擎的一个特性,而不能是使用的前提
更严格地说,使用FileWatch等手段进行文件变更检测并自动编译也不在我的考虑范围之内,因为这会造成额外的等待,像我这种手速极快的人可能编译速度跟不上
由此可以推出,前端的模板引擎应该是具备可在纯前端环境中解析使用的能力的
前端模板引擎要有良好的运行时调试能力
前端并不像后端,任何错误都可以有严格的日志记录和调用堆栈以供分析。由于用户行为的不确定性、执行环境的不确定性、各种第三方脚本的影响等,前端很难做到完全的错误处理和跟踪,这也导致前端必然存在需要直接在线上排查问题的情况
而当问题出现在模板引擎这一层时,就需要模板引擎提供良好的调试能力
一般来说,编译后生成的函数的调试能力是弱于原先手动编写的模板片断的,因为自动生成的函数基本不具备可读性和可断点跟踪性
因此在这一点上,一个供前端使用的模板引擎应该具备在特定情况下从“执行编译后函数获取HTML”换回“解析原模板再执行函数获取HTML”的模式,即应该支持在两种模式间切换
或者更好地,一个强大的前端模板引擎编译生成的函数,可以使用Source Map或其它自定义的手段直接映射回原模板片段,不过现在并没有什么模板引擎实现了这一功能
前端模板引擎要对文件合并友好在HTTP/2普及之前,文件合并依旧是前端性能优化中的一个重要手段,模板作为文件的一部分,依旧是需要合并的
在提供编译功能的模板引擎中,我们可以使用编译的手段将模板变为JavaScript源码,再在JavaScript的基础上做文件合并
但是如果我们出于上文所说的调试能力等原因希望保留原模板片段,那就需要模板引擎本身支持模板片段合并为一个文件了
大部分仅支持将一段输入的字符串作为模板解析的引擎并不具备这一能力,他们天生并不能将一整个字符串切分为多个模板片段,因而无法支持模板片段层面上的文件合并
需要实现对文件合并的支持,最好的办法就是让模板的语法是基于“片段”的,如下面的模板
[[title]]
<h2>{{title}}</h2>
[[content]]
<section class="article-content">
{{content}}
</section>
就由title和content两个片段组成,多个片段可以出现在一个文件中,这就在语法层面上支持了我们的文件合并
前端模板引擎要担负XSS的防范
从安全性上来说,前端对XSS的控制是有严格要求的
我在 单页面(SPA)开发会不会比多页面有更多的安全问题? - 张立理的回答 中有提到过,前端对XSS的防范比较合适的方法是使用“默认转义”的白名单式策略
基于此,一个合理的模板引擎是必须支持默认转义的,即所有数据的输出都默认经过escape的逻辑处理,将关键符号转为对应的HTML实体符号,以从根源上杜绝XSS的入侵路径
当然并不是所有的内容都必须经过转义的,在系统中免不了有对用户输入富文本的需求,因此需要支持特定的语法来产生无转义的输出,但时刻注意无转义输出才是特例,默认情况下必须是转义输出的
前端模板引擎要支持片段的复用这并不是前端模板引擎的需求,事实上任何模板引擎都应该支持片段的复用,后端如Velocity、Smarty等无不拥有此功能
所谓片段复用,应该有以下几个层次的应用:
- 一个片段可以被引入到另一处,相当于一个变量到处用的效果
- 一个片段被引入时,可以向其传递不同的数据,相当于一个函数到处用的效果
- 一个片段可以被外部替换,但外部不提供此片段的话保持一个默认的内容,类似设计模式中的策略模式
满足第1和第2点的模板引擎并不少,而满足第3点的前端模板引擎却不多见,而后端的Razor、Smarty等都具备这一功能
话说我当时设计我们自己的模板引擎的第3个版本时,就想出了block这一个概念来实现第3点,在做完交付将近半年之后,有人告诉我说Smarty上就有这概念,顿时有种不知应该高兴还是悲伤的不知所措感。还好他并没有怀疑我直接抄了别人的功能,不然真是冤枉
前端模板引擎要支持数据输出时的处理
所谓数据输出时处理,指一个数据要在输出时做额外的转换,最常见的如字符串的trim操作,比较技术性的如markdown的转换等
诚然数据的转换完全可以在将数据交给模板引擎前就通过JavaScript的逻辑处理完,但这会导致不少有些丑陋又有些冗余的代码,对逻辑本身的复用性也会造成负面的影响
通常模板引擎对数据做额外处理会使用filter的形式实现,类似bash中的管道的逻辑。filter的实现和注册也会有不同的设计,如mustache其实注册的是fitler工厂,而另一些模板引擎则会直接注册filter本身,不同设计有不同的考量点,我们很难说谁好谁坏
但是,模板引擎支持数据的输出处理后,会另我们在编码过程中产生一个新的纠结,即哪些数据处理应该交由模板引擎的filter实现,哪些应该在交给模板引擎前由自己的逻辑逻辑实现。这个话题展开来又是一篇长长的论述,于当前的话题无关就略过吧
前端模板引擎要支持动态数据
在开发过程中,其实有不少数据并不是静态的,如EmberJS就提供了Computed Property这样的概念,Angular也有类似的东西,Backbone则可以通过重写Model的get方法来变相实现
虽然ES5在语言层面上直接提供了getter的支持,但我们在前端开发的大部分场景下依旧不会使用这一语言特性,而会选择将动态的数据封装为某种对象的get等方法
而模板引擎在将数据转为HTML片段的过程中,同样应该关注这一点,对这些动态计算的数据有良好的支持
说得更明白一些,模板引擎不应该仅仅接受纯对象(Plain Object)作为输入,而应该更开放地接受类似带有get方法的动态的数据
一个比较合理的逻辑是,如果一个对象有一个get方法(模板引擎决定这个接口),则数据通过该方法获取,其它情况下视输入的对象为纯对象(Plain Object),使用标准的属性获取逻辑
前端模板引擎要与异步流程严密结合前端有一个很大的特点,就是到处充斥着异步的流程。由于JavaScript在浏览器提供的引擎中单线程执行的特性、大部分与IO相关的API都暴露为异步的事实,以及多数模块定义规范中模板的动态获取是异步的这一现象,注定我们无法将这个世界当作完全同步来看
一个很常见的例子是,我们有一个AMD模块存放了全局使用的常量,模板引擎需要使用这些常量。当然我们可以在使用模板引擎之前让JavaScript去异步获取这一模块,随后将常量作为数据传递给模板引擎,但这是一种业务与视图相对耦合的玩法,出于强迫症我并不觉得这是一个漂亮的设计,所以我们希望直接在模板中这么写:
<footer>{{$globals.ICP_SERIAL}}</footer>
模板引擎支持异步是一个比较具有挑战性的话题,我的计划是在我们自己的模板引擎的下一个版本中尝试实现。这其中涉及很多的技术点,比如:
- 模板的输出本身成了异步的方法,而不再像现在一样直接返回字符串
- 分析模板对异步操作的依赖,整个字符串的拼接逻辑被打断成多个异步
- 异步是需要等待的,且等待是未知的,从性能上考虑,是否需要考虑Stream式的输出,以便完成一段提供一段
- 是提供内置的固定几种异步逻辑,还是基于Promise支持任何自定义的异步逻辑,在复杂度和实用性上作出平衡
至今我还没有完全明确模板与异步结合的方式和接口,这个话题也没办法继续深入探讨了
前端模板引擎要支持不同的开发模式前端发展至今,有很多不同的开发模式,比如:
- 最普通的HTML页面,使用DOMContentLoaded等事件添加逻辑,特定交互下局部刷新页面
- 采用传统的MVC模型进行单页式开发
- 使用MVVM方式以数据为核心,数据与视图方向绑定进行开发
- 基于Immutable Data进行数据比对Diff转DOM更新的开发(其中可能有Virtual DOM的引入)
- 能够从模板中提取“这一模板对哪些数据有依赖”的元信息
- 能够知道一个数据变化引擎的是模板的哪一块,而不至于整个刷新
而通用模板引擎很少提供这两个特性,所以没办法对不同的前端开发模式进行全面到位的支持
从模板引擎本身的实现上来说,一种方法是直接将模板解析后的类似AST的结构暴露出去,供其他框架合理地处理,同时提供对模板局部的刷新功能(也可与前面所说的模板片段一起考虑),但是大部分模板引擎为了性能等考虑,是不会解析出类似AST的语法结构来的
前端模板引擎要有实例间的隔离
在大型的前端项目,特别是单页式的项目中,会有完全未知个数的模板片段同时存在,如果这些片段是带有名称(出于复用的考虑)的,就很容易造成名称上的冲突
对于同一层级的逻辑(如大家都是业务层代码,或者大家都是控件层代码),名称冲突是可以通过一些开发时的约定来解决的。但不同层之间,由于封装性的要求,外部不应该知道一些仅内部使用的片段的名称,此时如果不幸有名称与其它层有冲突,会让情况变得比较麻烦,这类问题甚至都不容易跟踪,往往会导致大量的精力和时间的浪费
因此,一个好的模板引擎应该是多实例的,且不同实例间应该相互具备隔离性,不会出现这种不可预期的冲突
将这个话题再往深地研究,就会发现单纯的隔离是不够的,不同层间除了不冲突的需求,同样还有片段复用的需求,我们还会需要不同模板实例间可以开放一些固定的片段共享,因此模板引擎各个实例的关系是一种组合依赖但又具备基本的封装和隔离的状态
说了这么多,其实现在市面上大致是没有一个模板引擎能满足全部这些条件的,至少“异步流程集成”和“多开发模式支持”这两点就不是一个普通的模板引擎会去考虑的场景,只有我们这种大型的系统才会遇到并在这方向上产生一些思考
因此在选择或设计开发模板引擎时,这些准则可以给你作一个参考,却不需要完全去遵从
推荐自己做的东西就好像把初中二年级写的小说给别人看一样充满羞耻感,所以我就不推销我们自己的产品了……
为啥我不把这些写成博客去骗下季度的部门稿费- -
首先要区分出(传统的)string-based模板引擎和(新潮的)dom-based模板引擎。
string based模板引擎的目标是输出字符串,几乎是所有时候,它的输入也是字符串,也就是所谓的模板。
string based模板引擎当中应用最广泛的,我猜是PHP的Smarty模板引擎,如果你对此有了解,那么所谓string based模板引擎的理解就没什么问题了。
string based模板引擎的输出并不一定是要HTML,其实你想输出什么都可以,比如我经常用模板引擎来输出ini文件神马的,还有公司使用的各种结构化格式的配置文件,还用来生成过CSS文件(iconfont平台的自动构建神马的),甚至用来输出过shell和SQL脚本(所谓板砖一般的代码)。
但是类似Jade这类的引擎,它基本上就只能输出标记语言,比如HTML/XML了,它就是为此而设计的。
至于题目“有哪些好用的前端模板引擎”,JS这面我觉得佳作来自国内的ecomfe/etpl · GitHub 和aui/artTemplate · GitHub,首先它们的速度都非常快,这对于大流量的服务端来说是很重要的,其次它们的需求出发点都是国内的知名互联网公司,比较符合国情(笑)。根据我自己的体验(用的不多),比国外的轮子要好。当然我自己也造了一个轮子LiuJi-Jim/raze-tpl · GitHub,吸收了这两个的一些优点,也有自己的风格和优点,不过属于玩票性质,BUG没功夫修,不建议任何人拿去用在自己的项目里(我也只是用在我自己的项目里,没在公司项目用,逃)……
而dom-based模板引擎,通常输出就直接是dom了(当然,很多dom-based模板引擎也可以很方便的挂载string输出端,从而在服务端也能输出),输入也不一定,可能就是已经存在的DOM树(比如AngularJS直接写在页面上的时候),可能是字符串(如AngularJS使用字符串模板的时候)也可能是它们自己定义的某种语言(比如React之于JSX)。前者需要先把字符串解析为语法树;后者就相当于给你一点语法糖,直接让你写一个AST了。有了AST,再在其中寻找出来一些“模板语法”,比如变量binding啊、比如循环、条件啊什么的。
dom-based模板引擎基本上不考虑输出HTML/XML以外的东西。
相比之下dom-based模板引擎可以实现像Matt-Esch/virtual-dom · GitHub这类的东西,在数据更新的时候实现最小操作,并不像string-based模板引擎那样,可能改了一个值就要重新生成巨大的一部分字符串。
string-based模板引擎在数据更新这个问题对于交互比较多的页面这是不友好的,意味着即使你用模板引擎生成了HTML代码,再把它innerHTML成一堆DOM,你还是得用原本的方式(比如jQuery)去操作这些DOM实现交互,这个过程中,模板引擎仅仅起到了帮你生成那堆DOM这一个问题,后面怎么去玩他们的问题就没下文了。
个人认为,在浏览器端,string-based模板引擎的应用场景越来越有限,string-based模板引擎对现在提倡的组件化开发其实是挺不友好的。与此同时,因为MV*——尤其是MVVM已经越来越被认可代表了先进生产力的发展方向,而MVVM对dom-based模板的依赖几乎是与连体婴的关系。
随着node.js服务端越来越被人接受,string-based模板引擎在做一些以输出页面为主的服务当中还是很好用的。但在dom-based模板引擎大炒“同构渲染”的趋势之下,string-based模板引擎的生存空间还是略微受到一些挤压,但因为在需求有限的场景中,简单粗暴出活快不用加班才是目的,string-based模板引擎依然顽强的生存着……
本文作者祈澈姑娘,转载请声明
前端的技术日渐更新,最近得空,将前端常见的框架总结了一下,在开发的过程之中,有了这些,不断能够提高自己的工作效率,还可以在工作之余了解更多。
1.Layui
Layui
是一款采用自身模块规范编写的国产前端UI框架,遵循原生HTML/CSS/JS的书写与组织形式,门槛极低,拿来即用。从核心代码到API的每一处细节都经过精心雕琢,非常适合界面的快速开发。,从核心代码到API的每一处细节都经过精心雕琢,非常适合界面的快速开发。Layui还很年轻,首个版本发布于2016年金秋,她区别于那些基于MVVM底层的UI框架,却并非逆道而行,而是信奉返璞归真之道。准确地说,她更多是为服务端程序员量身定做,你无需涉足各种前端工具的复杂配置,只需面对浏览器本身,让一切你所需要的元素与交互,从这里信手拈来。
经典模块化前端框架
2.NEC:
官方网址:http://nec.netease.com/case
你是否常常碰到以下问题:你总是看不懂他写的代码,或者读起来很吃力;你需要改他的代码却无从下手,或总是要去问他这里是什么改了会不会影响其他代码;你和他一起开发一个产品,你总是怕代码和他有冲突或互相影响;你的代码在多次维护任务之后变得越来越臃肿,越来越难以维护,解决以上问题只需一种方法——读我们的规范!
国产web前端框架推荐之–NEC
3:amaze UI
官方网址:http://amazeui.org/
之前公司的网站被黑客攻击之后,整个网站的东西都用不了了,处于丢失和瘫痪的状态,楼主毫不犹豫在这个网站上找了一个框架,仅仅两三天的时间,就成功挽救了这一糟糕的局面,还是要感谢我们这强大的框架,妹子UI,适配pc端和移动端,功能齐全,网站开发什么的,都SO
easy
中国首个开源 HTML5 跨屏前端框架.
4.NEJ
NEJ全称:Nice Easy Javascript 是由网易前端组工程师们发起创建的简洁,美观,真正的跨平台web前端开发框架;在适配性上支持桌面及移动平台、浏览器及混合应用开发,补丁模式无缝扩展适配平台,配置方式灵活定制目标平台
5.boostrap
框架官方网址:http://www.bootcss.com/
这个我就不多说了,大多数人都在用这个框架来开发,官方文档的API完整可靠,还有各种Bootstrap相关优质项目推荐,前端开发首选框架
简洁、直观、强悍的前端开发框架,让web开发更迅速、简单。
6:Foundation
Foundation 是一个易用、强大而且灵活的响应式前端框架,用于构建基于任何设备上的响应式网站、 Web应用和电子邮件。结构语义化、移动设备优先、完全可定制。
响应式前端框架
7.Jquery代码库
官方网址:http://www.jqueryui.org.cn/
基于Jquery的开源网页用户界面代码库:
8.jQuery插件库
官方网址:http://www.jq22.com/
史上最全的jQuery效果,包括了开发所需要的所有需求的demo,如果有不会的东西,就来jQuery插件库吧,这里总有一些你想要的,还在等什么?
9.FrozenUI
官方网址:http://frozenui.github.io/
随心所用的样式组件,更显灵动的JS插件,酷炫好玩的案例秀,提供的Animation
case,把业务上有趣好玩的案例沉淀下来,帮助日后能更快速找到设计灵感。Frozen
UI是一个开源的简单易用,轻量快捷的移动端UI框架。基于手Q样式规范,选取最常用的组件,做成手Q公用离线包减少请求,升级方式友好,文档完善,目前全面应用在腾讯手Q增值业务中。
移动端开发专用框架:
10:SUI
SUI
是一套基于bootstrap开发的前端组件库,同时她也是一套设计规范。通过SUI,可以非常方便的设计和实现精美的页面。同时sui还有移动端版本msui,msui是阿里巴巴共享业务事业部UED团队的作品。目的是为了手机H5页面提供一个常用的组件库,减少重复工作。
搭建手机H5应用:
11:AUI
AUI
2.0是一套全新的AUI框架,在1.X基础上进行了重新架构。结合实际项目出发,站在开发者和项目的角度,重新定义AUI框架。在2.0中使用了大量弹性响应式布局,采用容器+布局结构+控件的嵌套形式,方便开发者快速布局样式。我们充分吸取了AUI使用者的反馈意见和借鉴了市场上其他优秀UI框架,完成了2.0版本的开发。2.0遵循Google
Material 设计规范,使用MIT开源协议。
12:MUI:
官方网址:http://dev.dcloud.net.cn/mui/
最接近原生APP体验的高性能前端框架,相信这个大家都不陌生:鉴于之前的很多前端框架(特别是响应式布局的框架),UI控件看起来太像网页,没有原生感觉,因此追求原生UI感觉也是我们的重要目标MUI以iOS平台UI为基础,补充部分Android平台特有的UI控件
13:Semantic UI
官方网址:http://www.semantic-ui.cn/
Semantic作为一款开发框架,帮助开发者使用对人类友好的HTML语言构建优雅的响应式布局。更快地设计赏心悦目的网站
官方网址:http://www.oschina.net/p/aliceui?fromerr=mgWZvlr0
Aliceui是支付宝的样式解决方案,是一套精选的基于 spm 生态圈的样式模块集合,是 Arale 的子集,也是一套模块化的样式命名和组织规范,是写 CSS 的更好方式。
H-ui是轻量级前端框架,简单免费,兼容性好,适用于中国网站。H-ui是一个相对成长比较慢的前端框架,相比目前行业众多框架还有很多不足。但初心不改,实实在在把事做好,做用户最喜欢的框架。
官网地址:https://github.com/weui/weui
weUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信 Web 开发量身设计,可以令用户的使用感知更加统一。包含button、cell、dialog、 progress、 toast、article、actionsheet、icon等各式元素。
YDUI
Touch 专为移动端打造,在技术实现、交互设计上兼容主流移动设备,保证代码轻、性能高;使用 Flex
技术,灵活自如地对齐、收缩、扩展元素,轻松搞定移动页面布局;实现强大的屏幕适配布局,等比例适配所有屏幕。什么?用得不开心?轻松切换 px;自定义JavaScript组件、Less文件、Less变量,定制一份属于自己的YDUI;
一只注重审美,且性能高效的移动端&微信UI。
文末彩蛋:前端框架源码:http://www.mycodes.net/169/
各种模板应有尽有,提高开发的效率,升职加薪不是梦。