前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Web 前端模板引擎的选择

Web 前端模板引擎的选择

作者头像
一墨编程学习
发布于 2018-10-22 08:00:35
发布于 2018-10-22 08:00:35
3K00
代码可运行
举报
运行总次数:0
代码可运行

模板引擎负责组装数据,以另外一种形式或外观展现数据。 浏览器中的页面是 Web 模板引擎最终的展现。

无论你是否直接使用模板引擎,Web 模板一直都在,不在前端就在后端,它的出现甚至可以追溯到超文本标记语言 HTML 标准正式确立之前。

服务器端的模板引擎

我所知道最早的 Web 模板引擎是 PHP,它正式诞生于 1997 年,工作在服务器端。让我们看看 PHP 官方的 intro-whatis:

HPer 普遍赞同 PHP 本身就是最天然、原生的 PHP 模板引擎,因为她本来就是。在 PHP 的世界里多次出现过再包装的模板引擎,著名的有 smarty。

其它服务器端语言很多都有 HTML 模板引擎,比如 JSP、mustache。

毫无疑问,这些服务器端模板引擎最终生成的结果是 HTML(XML) 字符串,处理流程逻辑使用宿主语言本身的语法实现。

它们的共同特征:HTML 只是个字符串, 最终结果可能还需要类似 Tidy 这样的清洁或修正验证工具。

这里提出一个问题:二次封装的 smarty 有存在的必要么?

浏览器端的模板引擎

我所知道最早的前端模板引擎是 jCT,它托管于 Google Code,诞生于 2008 年,宿主语言是 JavaScript,工作在浏览器中。

今天在 OSC 搜索 JavaScript 模板引擎你会得到 100+ 个结果,下边列举一些:

轻量度:tpl.js、T.js 认知度:arttemplate、mustache.js、doT.js、handlebars.js、pug DOM-tree-based:domTemplate、transparency、plates VDOM-based:htmltemplate-vdom、virtual-stache、html-patcher 流行框架:Vue.js、ReactJS、riot Real-DOM:PowJS

它们的共同特征:全都支持插值。

这里还有 templating-engines 受欢迎度的对比,甚至 best-javascript-templating-engines 投票及正反方的理由。

如何选择

我认为存在即合理,每个引擎、框架总有可取之处,至少在你的应用里,在某个时代,所以本文不会评论某个引擎哪一点不好,那样是不客观的。现在回答前边提到的问题:smarty 有存在的必要么?我的答案是:有。理由很简单,看给谁用、看大背景。对于前后端没有分离的应用,或前端人员对后端语言不够熟悉,或因岗位职责需要,那么前端人员掌握一种比较通用的模板语法(语言)是现实的,反之让 PHPer 自己去使用 smarty 那就太浪费技能了。

下面是通常意义上的引擎选择建议:

前提,选择的引擎能满足数据渲染需求,且不和现有依赖冲突,如果你已经非常熟悉某个引擎,那你已经有答案了。 是一次性的项目需求么? 是的话直接选择轻量的,学习复杂度最低的。 是要做组件开发么? 引擎支持预编译结果,不必每次都实时编译么? 要跨平台么? 有官方提供支持的,首选类 React-JSX 的引擎或纯粹的 VDOM 引擎。 选择学习或维护复杂度最低的,众所周知,开发者对调试的时间超过写代码的时间深恶痛绝。 最后才是性能对比,性能对比是一件非常细致的工作,他人的对比结果不一定符合你的场景。

我认为应该弱化语法风格的对比,偏好是没有可比性的,一些语法甚至有特殊的背景原因。

为什么最后才是性能对比?

性能的确很重要,但如果性能还没有影响到你的应用体验度,那就忽视它。很难真实地模拟应用场景,通常只有通过真实场景来检验,目前的测试工具还达不到这种效果。

前述问题有些有固定答案,下面讨论余下的问题:如何考虑组件开发、支持预编译、复杂度?

组件开发

进行组件开发已经不再是选择模板引擎的问题了,这是生态环境选择的问题。如果你的应用需要更快地完成,那么时间点是第一位的,就选择流行框架,有足够多的组件让你使用或参考。如果你的应用有独立的生态环境,需要技术选型以便长期维护,那继续看下文。

预编译

预编译应该具备:

编译结果在目标环境中不再需要编译过程。 编译结果可调试性,这意味着结果应该包含原生 ECMAScript 代码,而不是纯粹的数据描述。 大家都知道 React-JSX 是支持预编译的,官方的说法是 React Without JSX,即总是 build 过的。

一些基于字符串处理的引擎也支持预编译。如果你需要预编译,建议抛弃编译结果依然是基于字符串拼接的引擎,那样还不如不预编译,那是 HTML5 未被广泛支持之前的技术手段。

至少也要有类似 React-JSX 这样的编译结果才具有可调试性。备注:Vue.js 支持多种模板引擎,可达到同样的效果。

原 ReactJS 代码,其中用到了 Web Components 技术:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class HelloMessage extends React.Component {
  render() {
    return <div>Hello <x-search>{this.props.name}</x-search>!</div>;
  }
}

编译后:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class HelloMessage extends React.Component {
  render() {
    return React.createElement(
      "div",
      null,
      "Hello ",
      React.createElement(
        "x-search",
        null,
        this.props.name
      ),
      "!"
    );
  }
}

不少 VDOM 引擎也可以编译类似效果,比如 htmltemplate-vdom。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  <script>
        var id = 3;
        var env = {
            people: [
                {
                    id: 'id1',
                    name: 'John',
                    inner: [{ title: 'a1' }, { title: 'b1' }],
                    city: 'New York',
                    active: true
                },
                {
                    id: 'id2',
                    name: 'Mary',
                    inner: [{ title: 'a2' }, { title: 'b2' }],
                    city: 'Moscow'
                }
            ],
            githubLink: 'https://github.com/agentcooper/htmltemplate-vdom',
            itemClick: function(id) {
                env.people.forEach(function(person) {
                    person.active = String(person.id) === String(id);
                });
                loop.update(env);
            }
            // Omitted ....
        };
    </script>

复杂度

很难用唯一的标准去评判两个引擎哪个复杂度低,这是由使用者的思维模式不同造成的。例如前边列出的引擎在使用上以及预编译结果上的区别,不同使用者感触是不同的,这正是不同引擎存在的合理性、价值性。

有的使用者认为这个应用场景有字符串模板就满足了需求,轻量够用。 有的使用者认为字符串拼接技术的模板引擎不够强壮,不够时代感。 有的使用者认为OOP 够理性,够逻辑,够抽象。 有的使用者认为原生 HTML 才叫前端。 有的使用者认为 VDOM 适用性更广。

这些评判都有各自的理由,着眼点不同,标准也就不同了。但是我们还是可以从它们的共性去考虑它们的复杂度。

字符串类模板通常都很轻量,不在本节讨论范围之内。对于非字符串模板复杂度评判的共性标准是什么?我认为,可以考量数据绑定的复杂度。

本文所指的数据绑定不只是插值,还包括上下文以及事件,甚至是整个运行期的宿主环境。

事实上至少需要达到 VDOM 级别的引擎才具有这种能力,因为通过 VDOM 可以映射到真实的 DOM 节点。

大概有几种模式(组合):

1.入口参数是个 Object,模板中的变量 x 是该对象的 .x 属性,例:virtual-stache-example 2.特定语法或属性,比如:Vue.js 的 <a v-on:click="doSomething">...</a>,属性 computed、methods 3.抽象的语义化属性,比如:Vue.js 的 active 这个词适用于多种场景,容易理解且不产生歧义 4.不负责绑定,需要使用者非常熟悉原生方法,用原生方法进行绑定,比如:PowJS

这些模式只是理论方面的,通常是模板引擎设计者要解决的问题。对于使用者来说不如直接问:

1.可以在 HTML 模板中直接写最简单的 console.log(context) 来调试么? 2.可以在多层 DOM 树绑定或传递不同的上下文参数么? 3.可以在多层 DOM 树内层向上访问已经生成的 Node 么?

模板引擎团队会给你正确的解决办法,但通常和问题字面描述的目标有所差异。我觉得这就是你评判选择的关键,你对官方给出的正确方法的认可度。

嵌入到 DOM 中

嵌入到 HTML 中

PowJS 是这么实现的:

实现模板必须要实现的指令 预编译输出原生 ECMAScript 代码 模板语法结构与 ECMAScript 函数写法一致 最终,写 PowJS 模板就像在写 ECMAScript 函数。

GoHub index 中的写法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <details func="repo" param="data" if="is.object(data.content)&&!sel(`#panel details[sha='${data.sha}']`)"
    open
    let="ctx=data.content"
    sha="{{data.sha}}"
    origin="{{ctx.Repo}}"
    repo="{{data.owner}}/{{data.repo}}"
    subdir="{{ctx.Subdir||''}}"
    filename="{{ctx.Filename}}"
    render=":ctx"
    do="this.renew(sel(`#panel details[repo='${data.owner}/${data.repo}']`))"
    break
  >
    <summary>{{ctx.Description}}</summary>
    <div if="':';" each="ctx.Package,val-pkg">
      <p title="{{pkg.Progress}}: {{pkg.Synopsis}}">{{pkg.Import}}</p>
    </div>
  </details>
  <dl func="list" param="data"
    if="!sel(`#panel details[sha='${data.sha}']`)&&':'||'';"
    each="data.content,data.sha,val-rep"
    do="this.appendTo(sel('#panel'))">
    <details sha="{{sha}}" repo="{{rep.repo}}">
      <summary>{{rep.synopsis}}</summary>
    </details>
  </dl>
</template>

多数模板引擎都会实现 if 、each 这些指令,上面的 PowJS 模板中还有:

全局对象 is、sel 模板(函数)命名 repo 、list 模板(函数)入口形参 data 自定义局部变量 ctx 下层模板(函数)形参推导 data.sha->sha 遍历值到下层模板形参推导 (ctx.Package,val-pkg)->pkg 、(data.content,val-rep)->rep DOM 节点操作 this.renew、 this.appendTo,这直接渲染到页面 DOM 树 流程控制 break 伪节点 if="':';",渲染时根本不生成 div 节点,它是个伪节点,相当于块代码符号 "{}" 关键是整个模板结构,指令语义和 ECMAScript 函数完全一致:

没有数据绑定,你写的是 ECMAScript 函数,传参数好了,要什么绑定 没有事件绑定,每个节点都是真实存在的,直接写 addEventListener 就好了 要调试,随便找个 do 或 if 或 let 插入 _=console.log(x), 就好了,逗号表达式几乎可以无缝插入所有原生语句 所有的业务逻辑都是使用者自己写的,PowJS 只负责把他们粘合成一个函数 导出视图是 ECMAScript 源码,下图截取自演示 My Folders

image.png

那么 PowJS 是最终的选择么?PowJS 的理念是原生性,原生的 DOM,原生的 ECMAScript。

原生也同样是 PowJS 的问题所在,不是所有的使用者都喜欢原生,我相信有的使用者更喜欢更抽象风格,他们眼中的原生总是带了点 "原始"。

原生意味着你可以扩展,引入其它 library 进行搭配,但 PowJS 永远不会出现 define setter/getter实现的 watcher,那超出了模板引擎的范围,如果有那一定是独立的项目。

最后,我的观点依然是:你的需求才是选择模板的关键,适合你的才是好的。

这里推荐一下我的前端学习交流群:784783012 ,里面都是学习前端的,如果你想制作酷炫的网页,想学习知识。自己整理了一份2018最全面前端学习资料,从最基础的HTML+CSS+JS到移动端HTML5到各种框架都有整理,送给每一位前端小伙伴,有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的,正在学习的小伙伴欢迎加入学习。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.10.16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
浅谈前端框架原理
最近在看卡颂大佬的《React 设计原理》,看了第一章,就有一种醍醐灌顶的感觉,于是决定记录分享一下这一章的内容。这里也极力推荐各位小伙伴读一下。
CandyTong
2023/01/31
1.6K0
模板引擎随谈
模板引擎是为了解耦而产生的,从编程范型的角度来说,写模板属于 “声明式(Imperative)编程”。JSP 大概是最早接触也是最基础的模板引擎,本来写 Servlet 嘛,一大堆一大堆的 print,实在是没有任何结构性可言,然后 JSP 出现,先被处理成实质为 Servlet 的 Java 文件,编译以后变成 class,接着一样执行。所以本质是编译型的模板引擎,当然模板引擎也有解释型或者二者混合的。通常说来编译型的执行效率要高得多。只要是和显示相关的编程语言,都会发展出一套或者 N 套模板引擎,用得多了觉得很多情况下都大同小异。
四火
2022/07/18
1.9K0
模板引擎随谈
前端工程化-构建
构建的核心是资源管理。简单说,构建就是把前端工程师开发的源代码进行编译、压缩、打包等一系列操作,最终产出可以直接上线或者可供后端工程师的资源。 构建可以划分为纯前端构建和前后端协作构建。 这两个不是专业术语,如果你有更合适的称谓,欢迎指正。 所谓纯前端构建,就是说不涉及后端模板的构建,经过构建之后的前端代码可以直接上线。这种情形下大多是数据驱动UI的web应用,模板只负责提供空白的容器和基础的静态资源,UI的文档结构交由前端JavaScript实现。这个过程可以使用一些框架,比如近期较流行的React
寒月十八
2018/01/30
1.1K0
前端工程化-构建
PHP八大模板引擎
当我们在PHP中讨论模板引擎时,许多开发人员会告诉你,这是没有必要的,他们会说这是学习时间和资源的浪费,因为PHP本质上也是一个模板引擎。但是当你看过很多框架之后,你会发现很多框架都会有模板引擎的存在,所以说php中的模板引擎还是有必要了解一下的。
程序那些事儿
2023/07/24
1.2K0
PHP八大模板引擎
JavaScript模板引擎-artTemplate
项目中,部分模块(filter、toolbar)业务复杂,过多依赖jQuery去铺数据,导致整体性能不高,且使用jQuery操作导致代码量和冗余度增大,后期维护不变。 使用JavaScript模板引擎可以有效的实现界面与数据分离(解耦),大大提升开发效率,且重用性较高。
奋飛
2019/08/15
2.1K0
Github上开源的10大Javascript模板引擎,助力前端开发
目前前端主流的开发框架有Vue、React以及Angular等,但是依然有一部分开发人员并不会去使用这些框架,特别是一些偏向后端的开发者,可能依然在使用类似于jquery+Bootstrap的方式在开发一些项目,而且有些项目可能传统的方式更加合适。
双面人
2019/11/14
7.2K0
Web前端模板引擎之字符串模板
进入正文之前,我们先回顾一下在模板引擎出现之前,暂且称之为“石器时代”,我们是如何利用JS改变页面结构的。对于下面的代码:
Dickensl
2022/06/14
1.5K0
Web前端模板引擎之字符串模板
前端激荡三十年
前端,由浏览器诞生的那一刻便随之而生,经过不断的探索如何将复杂晦涩的底层数据以人能更好理解的形式展示出去,从开始时的能用到好用,从单调到炫彩,用户体验越来越被重视,前端作为计算机层面与用户最近的一层必须去变革与发展。
用户1462769
2019/08/09
5490
前端激荡三十年
收藏夹吃灰了:GitHub 上值得收藏的100个精选前端项目
codrops 一系列具有相当具有创意且有趣的前端效果的集合,是非常棒的学习资料,可以欣赏和下载使用。并且有些项目,也托管到了github仓库中
王小婷
2020/10/23
2.5K0
浅谈前端框架原理
最近在看卡颂大佬的《React 设计原理》,看了第一章,就有一种醍醐灌顶的感觉,于是决定记录分享一下这一章的内容。这里也极力推荐各位小伙伴读一下。
CandyTong
2023/02/24
8880
浅谈前端框架原理
Web前端学习 第5章 node基础教程7 模板引擎概述
上一节我们通过Koa创建了一个web服务器,并可以根据用户请求路径的不同响应不同的页面,但是每一个页面的内容都是通过字符串的方式给送给浏览器的,这样的开发方式并不友好,我们更希望直接发送html页面。
学习猿地
2020/06/19
5710
Web前端学习 第5章 node基础教程7 模板引擎概述
干货 | 前端模板引擎知多少
“ 前端框架日新月异,而其中的数据绑定已经作为一个框架最基础的功能。我们常常使用的单向绑定、双向绑定、事件绑定、样式绑定等,里面具体怎么实现,而当我们数据变动的时候又会触发怎样的底部流程呢? ” 模板数据绑定 数据绑定的过程其实不复杂: 1. 解析语法生成AST。 2. 根据AST结果生成DOM。 3. 将数据绑定更新至模板。 解析语法生成AST 抽象语法树(Abstract Syntax Tree)也称为AST语法树,指的是源代码语法所对应的树状结构。也就是说,对于一种具体编程语言下的源代码,通过构
腾讯NEXT学位
2019/06/03
1.2K0
干货 | 前端模板引擎知多少
史上最全的web前端学习教程汇总!
第一阶段:HTML+CSS HTML进阶、CSS进阶、div+css布局、HTML+css整站开发、 JavaScript基础:js基础教程、js内置对象常用方法、常见DOM树操作大全、ECMAscript、DOM、BOM、定时器和焦点图。 JS基本特效:常见特效、例如:tab、导航、整页滚动、轮播图、JS制作幻灯片、弹出层、手风琴菜单、瀑布流布局、滚动事件、滚差视图。 JS高级特征:正则表达式、排序算法、递归算法、闭包、函数节流、作用域链、基于距离运动框架、面向对象基础、 JQuery:基础使用悬着器、D
企鹅号小编
2018/01/11
9.9K2
史上最全的web前端学习教程汇总!
用JS实现一个模板引擎
开始手写之前,我们先看看模板引擎应该是什么样的,在用koa开发后台服务的时候,我们用过ejs模板引擎,其作用是把模板渲染成html代码。下面是一个具体的使用例子。
luciozhang
2023/04/22
1.7K0
2019年小白学习web前端路线图及学习攻略
Js基础教程、js内置对象常用方法、常见DOM树操作大全、ECMAscript、DOM、BOM、定时器和焦点图。
用户4962466
2019/07/16
4.9K0
2019年小白学习web前端路线图及学习攻略
前端最常用的模板引擎-Handlebars
接触过的模板引擎不算多,只用过jsp和ejs,jsp属于Java语系范畴也不算难,对于大前端来说,Handlebars怎么能够缺席,前端必须掌握技能之一,模板引擎Handlebars。
王小婷
2018/12/10
1.6K0
前端最常用的模板引擎-Handlebars
关于前端模板引擎
前端框架日新月异,而其中的数据绑定已经作为一个框架最基础的功能。我们常常使用的单向绑定、双向绑定、事件绑定、样式绑定等,里面具体怎么实现,而当我们数据变动的时候又会触发怎样的底部流程呢?
被删
2024/07/29
3710
关于前端模板引擎
前端技术的发展与演变
近年来,前端技术的发展迅速,但因为前端知识面庞大,在实际学习当中往往无法理清其中的脉络。下面从各种库、框架、插件的层面上,对前端知识点做一些简单的梳理。从软件工程上,将前端分为四个由浅及深的层面或阶段。 一、基础层(浏览器原生支持html/css/js) HTML超文本标记语言,用标签构建网页的内容。HTML5扩展了标签及其功能。 CSS层叠样式表,控制页面内容的表现。CSS3增加了更多的特效,比如文本效果和2D/3D转换,以及动画。 JavaScript的原生API(包括DOM、BOM、Style样式、C
小古哥
2018/03/08
1.5K0
这些前端新技术你很难再忽视了 —— Svelte
可以粗暴简单这样记忆,Svelte 和 Vue 是一对,SolidJS 和 React 是一对。书写风格 Svelte 和 Vue 很像;而 SolidJS 和 React 很像;
掘金安东尼
2022/08/22
1.2K0
这些前端新技术你很难再忽视了 —— Svelte
mustache模板引擎
用法描述:比如数组arr中的数据渲染到视图中,首先在script标签中遍历arr数组,然后通过document.getElementById 去创建一个节点(孤儿节点),然后在把遍历的数据给每一个孤儿节点,
Shoulds
2022/08/09
1.5K0
mustache模板引擎
相关推荐
浅谈前端框架原理
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验