EJS[0]-如何使用EJS
EJS[0]-如何使用EJS
最近做的一个新项目,所以想着换一个新的模版引擎尝试一下。(之前我们一直在使用
handlebars
) 本次源码分析所使用的是TJ大神开发的1.x版本 当然现在该项目已经停止维护了,目前正在维护的是2.x版本
什么是EJS
EJS
是一个JavaScript
模版库,用来将EJS
模版结合着JSON
数据转换为HTML
并且可以直接在模版中写JavaScript
的语法
简单的示例
let template = '<h1>Hello, <%= name %></h1>'
let data = {
name: 'Niko Bellic'
}
let renderStr = ejs.render(template, data)
console.log(renderStr) // => <h1>Hello, Niko Bellic</h1>
EJS
模版主要还是HTML
标签,仅仅添加了几对特定的标签(<% %>
, <%= %>
, <%- %>
, <% -%>
, <%# %>
)。
为什么要用EJS
近年来,前端各种MV*框架层出不穷,React
,Angular
,Vue
,当然这应该也是未来几年的趋势了,但是这些大都是前端运行时进行渲染,动态的生成HTML
。 (React
是有着服务端渲染的解决方案,为了解决SEO的问题)
但是EJS
这类的模版引擎是不依赖于宿主语言环境的,只要是JavaScript
即可,也就是说可以用于server
端(node.js
)直接渲染,返回给前端渲染好的页面。(这个在大部分后台页面的开发中还是需要的)
当请求某个链接时,直接将渲染完成的页面呈现给用户,主要的作用有两点:
- 避免了代码都存在前端,被某些恶意用户看到。
- 对搜索引擎SEO更友好。
当然,MV*
框架依然是近几年的趋势,也是建议多去使用和研究那些框架,但是模版引擎和前端的那几个框架并不冲突,也是可以一起使用的。
如何使用EJS
EJS
提供了数个标签来供我们使用,在标签内可以直接写JavaScript
代码,如果使用服务端来渲染,你甚至可以直接引用一些npm
包,来做一些想做的事情。
<% code %>
EJS
会执行标签内的代码,一般用于逻辑处理或者循环创建使用。
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>
如上文在EJS
处理后的代码应该是类似这个样子的。(源代码比这个内容更丰富一些。。。)
(function () {
var buf = []
if (user) {
buf.push('<h2>')
buf.push(user.name)
buf.push('</h2>')
}
return buf.join('')
})
<%- code %>
EJS
会将标签内的代码执行,并获取返回值,将返回值输出到字符串中。
<span><%= 'Hello' %></span>
<!-- convert -->
<span>Hello</span>
<%= code %>
<%= code %>
与<%- code %>
类似,只不过会将返回值进行转义后输出。
<span><%= '<hello />' %></span>
<!-- convert -->
<span><hello /></span>
<%# comment %>
昂。。这个标签里边的内容是作为注释存在的。。估计很少有人会用-.- 在模版生成后,会移除里边的内容
在标签后边添加-
这个有很多种写法都可以支持,比如:<% -%>
,<%= -%>
,<%- -%>
这样会移除该标签后边的第一个换行符(如果有的话)
<h1>
<%- 'Title' %>
</h1>
<!-- convert -->
<h1>
Title
</h1>
<!-- line -->
<h1>
<%- 'Title' -%>
</h1>
<!-- convert -->
<h1>
Title</h1>
模版提供的各种Config
cache
默认为false
,如果设置为true
则认为是开启了缓存模式,对相同filename
参数的模版会使用之前已经渲染好的。
前置条件:必须同时设置filename
参数
filename
cache
模式下作为一个存储的key
。
scope
可以通过该参数设置模版执行时的函数上下文。
即模版中this
的指向。
debug
默认为false
,如果设置为true
,则会在模版执行compile
时输出拼接好的JavaScript
代码。方便调试。
compileDebug
默认为开启,设置为false
则为关闭,在开启状态下,模版会在compile
执行时额外拼接代码的行信息,这样在报错时我们可以很方便定位是哪一行出的问题。
client
默认为false
,如果设置为true
则会在compile
函数中返回一个相对独立的Function
。
主要是体现在一些内置函数的引用上。
open
设置开始的界定符。默认为<%
close
设置结束的界定符。默认为%>
模版对外暴露的API
官方文档中写的接口为:
compile
、render
。 确实。。其他几个接口都不太常用,或者说,太难以使用,比如:parse
属于一个半成品,renderFile
又只能在node
环境下使用。
clearCache
清除缓存,将之前内存中存储的模版清空。 简单粗暴的一个函数。。。老铁,没毛病。
exports.clearCache = function () {
cache = {};
};
parse
参数 |
描述 |
---|---|
str |
要进行解析的模版字符串 |
options |
一系列的配置参数 |
解析模版字符串,将其转换为可执行的JavaScript
代码并返回。
P.S. 该函数的执行会返回一个JavaScript
脚本的字符串,我们可以通过new Function()
或者eval
(不推荐了)来执行该脚本获得渲染好的字符串。
compile
参数 |
描述 |
---|---|
str |
要进行解析的模版字符串 |
options |
一系列的配置参数 |
函数会调用parse
,并将生成好的脚本塞进一个函数中,并将函数返回,我们可以通过调用该函数来获得渲染好的字符串。
render
参数 |
描述 |
---|---|
str |
要进行解析的模版字符串 |
options |
一系列的配置参数 |
函数调用compile
,返回值即是渲染好的字符串。
renderFile
参数 |
描述 |
---|---|
path |
模版字符串存储的路径 |
options |
一系列的配置参数 |
fn |
获取到文件后执行的回调函数 |
该函数会将path
取出,取出对应的文件,然后将文件的文本作为模版字符串传入render
方法中。
fn
回调函数应遵守Error-First
的规则。(第一个参数为err
,后续参数为result
)
对外的API
除去clearCache
外的四个函数,是一个包含的关系,大致结构如下:
renderFile
[> readFile & callrender
]render
[> callcompile
& execute]compile
[> callparse
& wrap]parse
[> buildejs
template & return result]
一些完整的示例
仓库中存放了一些各种使用姿势的示例: https://github.com/Jiasm/ejs-examples
- 开发人员看测试之运行Github中的JBehave项目
- 如何高效地合并Spark社区PR到自己维护的分支
- 开发人员看测试之TDD和BDD
- AngularJS入门心得1——directive和controller如何通信
- AngularJS入门心得2——何为双向数据绑定
- AngularJS入门心得3——HTML的左右手指令
- AngularJS入门心得4——漫谈指令scope
- Enterprise Library深入解析与灵活应用(8):WCF与Exception Handling AppBlock集成[上]
- 苹果就“电池门”公开致歉;微信下拉任务栏新增小游戏;美团打车进入北京
- 新华三《中国城市数字经济指数白皮书》:深圳数字经济发展水平国内居首
- NodeMCU模块写入MicroPython固件
- 如何证明Application Domain的隔离性
- Enterprise Library深入解析与灵活应用(8):WCF与Exception Handling AppBlock集成[下]
- 我所理解的Remoting(1):Marshaling & Activation[上篇]
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- istio的安全(概念)
- 面试题系列第5篇:JDK的运行时常量池、字符串常量池、静态常量池,还傻傻分不清?
- Go by Example 中文版: 互斥锁
- Idea初始化配置大全,以后重装再也不用各种百度了
- 使用这种技巧,可以大大地提高前端布局效率
- Element-UI表格组件实现行拖拽排序
- Vue自定义指令实现拖拽功能
- 小程序 Canvas 层级问题
- JDK 8 新特性之函数式编程 → Stream API
- golang 单元测试框架实践
- 想要成为前端Star 吗?一首歌时间将React/Vue 应用Docker 化
- 60亿次for循环,原来这么多东西
- 不要再问我 in,exists 走不走索引了...
- 知乎太可恶了,一言不合就封号?
- 5年Java开发经验,面试挂在MySQL InnoDB上!大厂究竟多看重MySQL?