ejs的基本概念十分简单,一个html = 模板 + 数据,和传统的php字符串模板拼接很是类似.javascript
例如咱们有一个列表该列表展现一组新闻,理想中的状态以下:php
<article> <h2>新闻1</h2> <h2>新闻2</h2> <h2>新闻3</h2> <h2>新闻4</h2> <h2>新闻5</h2> </article>
若是数据是异步获取的,咱们能够利用for循环拼接字符串来实现内部的多个h2
而后再追加到html中.css
let data = [],result = ''; for (i=0,len = data.length;i<len;i++){ result += '<h1>'+data[i]+'</h1>>'; }
可是ejs更像是以下的样子(伪代码):html
/** * @param {string} template 字符串模板 * @param {object} data 模板须要的数据 */ function ejs(template,data) { return template(data); }
也就是说ejs须要一个字符串模板,和一个data也就是咱们的数据源.java
template是字符串模板基于html语法可是ejs提供了特殊符号用于控制咱们传入的数据如何填充到html中.node
这里就不说起了你能够去官网下载也可使用npm进行安装.git
我使用的版本是2.6.1
是目前的最新版本,网上的不少文章实际上有些已通过时了,由于API有些变更.github
ejs中文文档中有较新的API一览.express
ejs分为两个版本一个是CommonJs版本,另一个是AMD规范的版本.npm
后面的测试基本都是在浏览器中运行,我没有使用requireJs
直接使用script引入的ejs:
<script type="text/javascript" src="./node_modules/ejs/ejs.js"></script>
ejs会将自身挂载到window对象上,因此你只要console.log(ejs)
控制台有输出就说明安装成功了.
ejs.render('<h1><%= data %></h1>',{data:123});
返回:
<h1>123</h1>
render
方法只须要两个参数,和以前说的同样第一个为模板字符串,而二个为数据源.
ejs使用html做为模板的基础语言,因此你不须要进行学习任何额外的语法,须要了解的就是ejs给咱们提供的几个模板语法.
那么<%= %>
目前看来就是输出数据,ejs所作的仅仅是用123
来替换掉<%= data %>
而已.
在ejs提供的语法中能够直接使用javascript因此你能够很是容易理解使用复杂逻辑如何完成渲染的,咱们来看一个具体的例子:
const template = ` <article> <% news.forEach(item=>{ %> <h2><%= item %></h2> <% }) %> </article> `; const data = { news:['新闻1','新闻2','新闻3'] }; const htmlString = ejs.render(template,data);
返回的内容:
<article> <h2>新闻1</h2> <h2>新闻2</h2> <h2>新闻3</h2> </article>
实际上去除掉ejs提供了模板语法,内容就是这个样子的:
news.forEach(item=>{ '<h2>'+item+'</h2>' })
也就是说<% %>
的符号不会产生实际的输出,可是能够放置javascript代码用于控制中间代码块的执行流程.
const template = ` <article> <% data.forEach(item=>{ %> <% if(item.sexCode){ %> <h2><%= item.name+'的性别是女' %></h2> <% } else { %> <h2><%= item.name+'的性别是男' %></h2> <% } %> <% }) %> </article> `; const data = { data:[ { name:'小明', sexCode:0 } , { name:'小红', sexCode:1 } ] }; const htmlString = ejs.render(template,data);
输出:
<article> <h2>小明的性别是男</h2> <h2>小红的性别是女</h2> </article>
这个例子稍显复杂,可是他告诉咱们几点有价值的内容:
<% %>
用于存放javascript代码片断是肯定无疑的事情了,甚至在这个例子中咱们还执行了嵌套操做.<%= %>
实际上把内容看成表达式执行后再输出的,至少它有执行表达式的能力<% %>
用于执行其中的javascript代码<%= %>
会对其中的javascript代码html转译这里我就将官网的一览贴了过来而后每一个提供一个例子:
先看一下2,8,9这三个.
以前个人几个例子中包含了不少空格和换行缘由是由于使用的是默认的输出格式,例如咱们以前使用这个例子:
<article> <h2>小明的性别是男</h2> <h2>小红的性别是女</h2> </article>
来看一下修改后的效果.
使用删除空格符号:
<article> <%_ data.forEach(item=>{ _%> <%_ if(item.sexCode){ _%> <h2><%= item.name+'的性别是女' _%></h2> <%_ } else { %> <h2><%= item.name+'的性别是男' _%></h2> <%_ } _%> <%_ }) _%> </article>
输出的内容:
<article> <h2>小明的性别是男</h2> <h2>小红的性别是女</h2> </article>
能够看到确实少了一些内容,可是实际上空隙是由换行符号引发的,此次咱们来删除尾部的换行符号:
<article> <% data.forEach(item=>{ -%> <% if(item.sexCode){ -%> <h2><%= item.name+'的性别是女' -%></h2> <% } else { -%> <h2><%= item.name+'的性别是男' -%></h2> <% } -%> <% }) -%> </article>
输出的内容:
<article> <h2>小明的性别是男</h2> <h2>小红的性别是女</h2> </article>
虽然行数减小了不过格式乱掉了.
注意:若是不想保留换行和空格能够把方法的选项参数中的rmWhitespace
设置为true
.
<%- %>的使用
默认状况下在<%= %>
之间的html字符串会被作转译处理:
<%= '<h1>hello world</h1>' %>
返回:
<h1>hello world</h1>
使用<%- %>:
该模板语法不会转译html字符串
<%- '<h1>hello world</h1>' %>
返回:
<h1>hello world</h1>
<%# %>的使用
该标签不会在最终的结果中出现,做为模板中的注释:
<%# '<h1>hello world</h1>' %>
返回的结果:
<%% %>的使用.
该操做返回的是模板字符串(string):
<%% if(id){ %> <%% } %>
返回的结果:
<% if(id){ %> <% } %>
ejs渲染的API主要有三个分别是:
区别是:
ejs内部是有缓存系统的它会将模板字符串解析为一个数据结构后续的操做将不会在此解析模板.
compile就是返回了内部已经处理好模板字符串的函数,在有大量数据重复使用这套模板的时候就会带来性能提高,而对于render
和renderFile
来讲须要在选项中设置cache
为true
,对于render
方法还须要指定filename
选项.
这里也是照搬官网的:
include
使用绝对路径引入时会以此为根路径.echo
和print
)用于在模板语法内打印输出内容.true
时ejs内部的渲染都将为异步,内部使用(await/async).测试缓存对于性能的影响,使用的模板和数据以下:
const template = ` <article> <% data.forEach(item=>{ %> <% if(item.sexCode){ %> <h2><%= item.name+'的性别是女' %></h2> <% } else { %> <h2><%= item.name+'的性别是男' %></h2> <% } %> <% }) %> </article> `; const data = { data: [ { name: '小明', sexCode: 0 } , { name: '小红', sexCode: 1 } ] };
我使用render连续跑1000次使用的时间为480ms
.
使用compile
进行测试:
const demo = ejs.compile(template); console.time('start'); let i = 0, len = 1000; while (i < len) { demo(data); i++; } console.timeEnd('start');
最后的结果为15ms
,能够看到性能提高是很是明显的.
测试outputFunctionName
选项.
const data = { content:'hello world' }; const result = ejs.render(`<h1><% echo(content) %></h1>`,data,{ outputFunctionName:'echo' }); console.log(result)
输出:
<h1>hello world</h1>
测试async
选项.
const data = { content:'hello world' }; const result = ejs.render(`<h1><%= content %></h1>`,data,{ async:true }); result.then((result)=>{ console.log(result); })
输出:
<h1>hello world</h1>
网上的各类文章中都提到了ejs拥有内部缓存,给render
方法提供选项中包含filename
和cache
属性就能够以filename
进行命名而后挂载在ejs内部的缓存对象上.
可是各个文章描述的及其模糊,我查看render
和compile
的源码后也没有发现显式使用缓存的选项存在,不过依然找到了一个可使用缓存后的函数的方法.
// 不要此次的结果,使用缓存 ejs.render(template,data,{ filename: 'test', cache:true }); // 获取缓存后的函数 const cacheFun = ejs.cache.get('test'); console.time('start'); let i = 0, len = 1000; while (i < len) { cacheFun(data); i++; } console.timeEnd('start');
最后使用的时间为15ms
和使用compile
的速度一致.
我的猜想内部缓存功能是为了服务端渲染使用的或者为了配合express
使用,没有向浏览器端提供很好的支持.
注意:ejs.clearCache()
方法能够清空内部的缓存.
在通常的开发中咱们常常将网页切割为多个部分,例如最简单的切割就是将页面分为导航栏
`主体区域`页尾
三个部分.
在使用的时候常常变化的是主体区域,而页尾不常常变化,可是不少页面须要一样的页尾,这个时候咱们就能够将页尾单独拿出来作成一个模板.
ejs中可使用include
命令来插入其余的模板.(注意只能在服务端中操做)
新建两个文件:
header.ejs:
<h2> <%= content %> </h2>
footer.ejs:
<h2> <%= content %> </h2>
咱们编写如下代码:
const ejs = require('ejs'); const template = ` <%- include('./header',{content:'我是页头'}) %> <article> 我是内容区域 </article> <%- include('./footer',{content:'我是页脚'}) %> `; console.log(ejs.render(template,{ filename:'whatthefuck' // 这个操做中须要一个名称,和路径无关 }));
输出:
<h2> 我是页头 </h2> <article> 我是内容区域 </article> <h2> 我是页脚 </h2>
有其余须要的朋友能够去查看ejs的github或者中文官网,惟一的额外信息也就这里有了.
https://blog.csdn.net/xjl2713...https://www.jianshu.com/p/81e...
https://blog.csdn.net/zhangxi...
https://www.cnblogs.com/yedey...