摘要:基本概念的基本概念十分簡(jiǎn)單一個(gè)模板數(shù)據(jù)和傳統(tǒng)的字符串模板拼接非常相似例如我們有一個(gè)列表該列表展示一組新聞理想中的狀態(tài)如下新聞新聞新聞新聞新聞如果數(shù)據(jù)是異步獲取的我們可以利用循環(huán)拼接字符串來(lái)實(shí)現(xiàn)內(nèi)部的多個(gè)然后再追加到中但是更像是如下的樣子偽代
基本概念
ejs的基本概念十分簡(jiǎn)單,一個(gè)html = 模板 + 數(shù)據(jù),和傳統(tǒng)的php字符串模板拼接非常相似.
例如我們有一個(gè)列表該列表展示一組新聞,理想中的狀態(tài)如下:
新聞1
新聞2
新聞3
新聞4
新聞5
如果數(shù)據(jù)是異步獲取的,我們可以利用for循環(huán)拼接字符串來(lái)實(shí)現(xiàn)內(nèi)部的多個(gè)h2然后再追加到html中.
let data = [],result = ""; for (i=0,len = data.length;i"+data[i]+">"; }
但是ejs更像是如下的樣子(偽代碼):
/** * @param {string} template 字符串模板 * @param {object} data 模板需要的數(shù)據(jù) */ function ejs(template,data) { return template(data); }
也就是說(shuō)ejs需要一個(gè)字符串模板,和一個(gè)data也就是我們的數(shù)據(jù)源.
template是字符串模板基于html語(yǔ)法但是ejs提供了特殊符號(hào)用于控制我們傳入的數(shù)據(jù)如何填充到html中.
安裝這里就不提及了你可以去官網(wǎng)下載也可以使用npm進(jìn)行安裝.
我使用的版本是2.6.1是目前的最新版本,網(wǎng)上的很多文章實(shí)際上有些已經(jīng)過(guò)時(shí)了,因?yàn)锳PI有些變動(dòng).
ejs中文文檔中有較新的API一覽.
使用ejs分為兩個(gè)版本一個(gè)是CommonJs版本,另外一個(gè)是AMD規(guī)范的版本.
后面的測(cè)試基本都是在瀏覽器中運(yùn)行,我沒有使用requireJs直接使用script引入的ejs:
ejs會(huì)將自身掛載到window對(duì)象上,所以你只要console.log(ejs)控制臺(tái)有輸出就說(shuō)明安裝成功了.
渲染單個(gè)數(shù)據(jù)ejs.render("<%= data %>
",{data:123});
返回:
123
render方法只需要兩個(gè)參數(shù),和之前說(shuō)的一樣第一個(gè)為模板字符串,而二個(gè)為數(shù)據(jù)源.
ejs使用html作為模板的基礎(chǔ)語(yǔ)言,所以你不需要進(jìn)行學(xué)習(xí)任何額外的語(yǔ)法,需要了解的就是ejs給我們提供的幾個(gè)模板語(yǔ)法.
那么<%= %>目前看來(lái)就是輸出數(shù)據(jù),ejs所做的僅僅是用123來(lái)替換掉<%= data %>而已.
渲染多個(gè)數(shù)據(jù)在ejs提供的語(yǔ)法中可以直接使用javascript所以你可以非常容易理解使用復(fù)雜邏輯如何完成渲染的,我們來(lái)看一個(gè)具體的例子:
const template = `<% news.forEach(item=>{ %> `; const data = { news:["新聞1","新聞2","新聞3"] }; const htmlString = ejs.render(template,data);<%= item %>
<% }) %>
返回的內(nèi)容:
新聞1
新聞2
新聞3
實(shí)際上去除掉ejs提供了模板語(yǔ)法,內(nèi)容就是這個(gè)樣子的:
news.forEach(item=>{ ""+item+"
" })
也就是說(shuō)<% %>的符號(hào)不會(huì)產(chǎn)生實(shí)際的輸出,但是可以放置javascript代碼用于控制中間代碼塊的執(zhí)行流程.
有條件的渲染數(shù)據(jù)const template = `<% data.forEach(item=>{ %> <% if(item.sexCode){ %> `; const data = { data:[ { name:"小明", sexCode:0 } , { name:"小紅", sexCode:1 } ] }; const htmlString = ejs.render(template,data);<%= item.name+"的性別是女" %>
<% } else { %><%= item.name+"的性別是男" %>
<% } %> <% }) %>
輸出:
小明的性別是男
小紅的性別是女
這個(gè)例子稍顯復(fù)雜,但是他告訴我們幾點(diǎn)有價(jià)值的內(nèi)容:
<% %>用于存放javascript代碼片段是確定無(wú)疑的事情了,甚至在這個(gè)例子中我們還執(zhí)行了嵌套操作.
<%= %>實(shí)際上把內(nèi)容當(dāng)作表達(dá)式執(zhí)行后再輸出的,至少它有執(zhí)行表達(dá)式的能力
本質(zhì)<% %>用于執(zhí)行其中的javascript代碼
<%= %>會(huì)對(duì)其中的javascript代碼html轉(zhuǎn)譯
其他的模板語(yǔ)法這里我就將官網(wǎng)的一覽貼了過(guò)來(lái)然后每個(gè)提供一個(gè)例子:
<% "腳本" 標(biāo)簽,用于流程控制,無(wú)輸出。
<%_ 刪除其前面的空格符
<%= 輸出數(shù)據(jù)到模板(輸出是轉(zhuǎn)義 HTML 標(biāo)簽)
<%- 輸出非轉(zhuǎn)義的數(shù)據(jù)到模板
<%# 注釋標(biāo)簽,不執(zhí)行、不輸出內(nèi)容
<%% 輸出字符串 "<%"
%> 一般結(jié)束標(biāo)簽
-%> 刪除緊隨其后的換行符
_%> 將結(jié)束標(biāo)簽后面的空格符刪除
先看一下2,8,9這三個(gè).
之前我的幾個(gè)例子中包含了很多空格和換行原因是因?yàn)槭褂玫氖悄J(rèn)的輸出格式,例如我們之前使用這個(gè)例子:
小明的性別是男
小紅的性別是女
來(lái)看一下修改后的效果.
使用刪除空格符號(hào):
<%_ data.forEach(item=>{ _%> <%_ if(item.sexCode){ _%> <%= item.name+"的性別是女" _%>
<%_ } else { %><%= item.name+"的性別是男" _%>
<%_ } _%> <%_ }) _%>
輸出的內(nèi)容:
小明的性別是男
小紅的性別是女
可以看到確實(shí)少了一些內(nèi)容,但是實(shí)際上空隙是由換行符號(hào)引起的,這次我們來(lái)刪除尾部的換行符號(hào):
<% data.forEach(item=>{ -%> <% if(item.sexCode){ -%> <%= item.name+"的性別是女" -%>
<% } else { -%><%= item.name+"的性別是男" -%>
<% } -%> <% }) -%>
輸出的內(nèi)容:
小明的性別是男
小紅的性別是女
雖然行數(shù)減少了不過(guò)格式亂掉了.
注意:如果不想保留換行和空格可以把方法的選項(xiàng)參數(shù)中的rmWhitespace設(shè)置為true.
<%- %>的使用
默認(rèn)情況下在<%= %>之間的html字符串會(huì)被做轉(zhuǎn)譯處理:
<%= "hello world
" %>
返回:
hello world
使用<%- %>:
該模板語(yǔ)法不會(huì)轉(zhuǎn)譯html字符串
<%- "hello world
" %>
返回:
hello world
<%# %>的使用
該標(biāo)簽不會(huì)在最終的結(jié)果中出現(xiàn),作為模板中的注釋:
<%# "hello world
" %>
返回的結(jié)果:
<%% %>的使用.
該操作返回的是模板字符串(string):
<%% if(id){ %> <%% } %>
返回的結(jié)果:
<% if(id){ %> <% } %>API
ejs渲染的API主要有三個(gè)分別是:
compile(str, options)
render(str, data, options)
renderFile(filename, data, options,callback(err,str)) 在瀏覽器端無(wú)效
區(qū)別是:
render 傳入模板字符串和數(shù)據(jù)返回結(jié)果
compile 返回一個(gè)模板函數(shù),對(duì)這個(gè)函數(shù)傳入數(shù)據(jù)獲取結(jié)果
rednerFile 從文件中獲取模板
ejs內(nèi)部是有緩存系統(tǒng)的它會(huì)將模板字符串解析為一個(gè)數(shù)據(jù)結(jié)構(gòu)后續(xù)的操作將不會(huì)在此解析模板.
compile就是返回了內(nèi)部已經(jīng)處理好模板字符串的函數(shù),在有大量數(shù)據(jù)重復(fù)使用這套模板的時(shí)候就會(huì)帶來(lái)性能提升,而對(duì)于render和renderFile來(lái)說(shuō)需要在選項(xiàng)中設(shè)置cache為true,對(duì)于render方法還需要指定filename選項(xiàng).
選項(xiàng)參數(shù)這里也是照搬官網(wǎng)的:
cache 緩存編譯后的函數(shù),需要提供 filename
filename 被 cache 參數(shù)用做鍵值,同時(shí)也用于 include 語(yǔ)句
context 函數(shù)執(zhí)行時(shí)的上下文環(huán)境
compileDebug 當(dāng)為 false 時(shí)不編譯調(diào)試語(yǔ)句
client 返回獨(dú)立的編譯后的函數(shù)
delimiter 放在角括號(hào)中的字符,用于標(biāo)記標(biāo)簽的開與閉
debug 將生成的函數(shù)體輸出
_with 是否使用 with() {} 結(jié)構(gòu)。如果為 false,所有局部數(shù)據(jù)將存儲(chǔ)在 locals 對(duì)象上。
localsName 如果不使用 with ,localsName 將作為存儲(chǔ)局部變量的對(duì)象的名稱。默認(rèn)名稱是 locals
rmWhitespace 刪除所有可安全刪除的空白字符,包括開始與結(jié)尾處的空格。對(duì)于所有標(biāo)簽來(lái)說(shuō),它提供了一個(gè)更安全版本的 -%> (在一行的中間并不會(huì)剔除標(biāo)簽后面的換行符)。
escape 為 <%= 結(jié)構(gòu)設(shè)置對(duì)應(yīng)的轉(zhuǎn)義(escape)函數(shù)。它被用于輸出結(jié)果以及在生成的客戶端函數(shù)中通過(guò) .toString() 輸出。(默認(rèn)轉(zhuǎn)義 XML)。
root include使用絕對(duì)路徑引入時(shí)會(huì)以此為根路徑.
outputFunctionName 指定一個(gè)函數(shù)名稱(例如echo和print)用于在模板語(yǔ)法內(nèi)打印輸出內(nèi)容.
async 當(dāng)為true時(shí)ejs內(nèi)部的渲染都將為異步,內(nèi)部使用(await/async).
測(cè)試緩存對(duì)于性能的影響,使用的模板和數(shù)據(jù)如下:
const template = `<% data.forEach(item=>{ %> <% if(item.sexCode){ %> `; const data = { data: [ { name: "小明", sexCode: 0 } , { name: "小紅", sexCode: 1 } ] };<%= item.name+"的性別是女" %>
<% } else { %><%= item.name+"的性別是男" %>
<% } %> <% }) %>
我使用render連續(xù)跑1000次使用的時(shí)間為480ms.
使用compile進(jìn)行測(cè)試:
const demo = ejs.compile(template); console.time("start"); let i = 0, len = 1000; while (i < len) { demo(data); i++; } console.timeEnd("start");
最后的結(jié)果為15ms,可以看到性能提升是非常明顯的.
測(cè)試outputFunctionName選項(xiàng).
const data = { content:"hello world" }; const result = ejs.render(`<% echo(content) %>
`,data,{ outputFunctionName:"echo" }); console.log(result)
輸出:
hello world
測(cè)試async選項(xiàng).
const data = { content:"hello world" }; const result = ejs.render(`<%= content %>
`,data,{ async:true }); result.then((result)=>{ console.log(result); })
輸出:
瀏覽器端使用默認(rèn)緩存hello world
網(wǎng)上的各種文章中都提到了ejs擁有內(nèi)部緩存,給render方法提供選項(xiàng)中包含filename和cache屬性就可以以filename進(jìn)行命名然后掛載在ejs內(nèi)部的緩存對(duì)象上.
但是各個(gè)文章描述的及其模糊,我查看render和compile的源碼后也沒有發(fā)現(xiàn)顯式使用緩存的選項(xiàng)存在,不過(guò)依然找到了一個(gè)可以使用緩存后的函數(shù)的方法.
// 不要這次的結(jié)果,使用緩存 ejs.render(template,data,{ filename: "test", cache:true }); // 獲取緩存后的函數(shù) const cacheFun = ejs.cache.get("test"); console.time("start"); let i = 0, len = 1000; while (i < len) { cacheFun(data); i++; } console.timeEnd("start");
最后使用的時(shí)間為15ms和使用compile的速度一致.
個(gè)人猜測(cè)內(nèi)部緩存功能是為了服務(wù)端渲染使用的或者為了配合express使用,沒有向?yàn)g覽器端提供很好的支持.
注意:ejs.clearCache()方法可以清空內(nèi)部的緩存.
高級(jí)操作 包含其他模板在一般的開發(fā)中我們經(jīng)常將網(wǎng)頁(yè)切割為多個(gè)部分,例如最簡(jiǎn)單的切割就是將頁(yè)面分為導(dǎo)航欄`主體區(qū)域`頁(yè)尾三個(gè)部分.
在使用的時(shí)候經(jīng)常變化的是主體區(qū)域,而頁(yè)尾不經(jīng)常變化,但是很多頁(yè)面需要同樣的頁(yè)尾,這個(gè)時(shí)候我們就可以將頁(yè)尾多帶帶拿出來(lái)做成一個(gè)模板.
ejs中可以使用include命令來(lái)插入其他的模板.(注意只能在服務(wù)端中操作)
新建兩個(gè)文件:
header.ejs:
<%= content %>
footer.ejs:
<%= content %>
我們編寫以下代碼:
const ejs = require("ejs"); const template = ` <%- include("./header",{content:"我是頁(yè)頭"}) %>我是內(nèi)容區(qū)域 <%- include("./footer",{content:"我是頁(yè)腳"}) %> `; console.log(ejs.render(template,{ filename:"whatthefuck" // 這個(gè)操作中需要一個(gè)名稱,和路徑無(wú)關(guān) }));
輸出:
我是頁(yè)頭
我是內(nèi)容區(qū)域 我是頁(yè)腳
有其他需要的朋友可以去查看ejs的github或者中文官網(wǎng),唯一的額外信息也就這里有了.
參考https://blog.csdn.net/xjl2713...https://www.jianshu.com/p/81e...
https://blog.csdn.net/zhangxi...
https://www.cnblogs.com/yedey...
https://segmentfault.com/a/11...
https://ejs.bootcss.com/
https://github.com/mde/ejs
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/53206.html
摘要:基本概念的基本概念十分簡(jiǎn)單一個(gè)模板數(shù)據(jù)和傳統(tǒng)的字符串模板拼接非常相似例如我們有一個(gè)列表該列表展示一組新聞理想中的狀態(tài)如下新聞新聞新聞新聞新聞如果數(shù)據(jù)是異步獲取的我們可以利用循環(huán)拼接字符串來(lái)實(shí)現(xiàn)內(nèi)部的多個(gè)然后再追加到中但是更像是如下的樣子偽代 基本概念 ejs的基本概念十分簡(jiǎn)單,一個(gè)html = 模板 + 數(shù)據(jù),和傳統(tǒng)的php字符串模板拼接非常相似. 例如我們有一個(gè)列表該列表展示一組新聞...
摘要:而框架中最常用的兩個(gè)視圖引擎是和。實(shí)際上這些上下文對(duì)象就是會(huì)在視圖中使用到的變量。其實(shí)視圖緩存并不是緩存視圖實(shí)際上它緩存的視圖路徑。根據(jù)默認(rèn)視圖引擎將缺少拓展名的視圖文件補(bǔ)充完整。實(shí)際上存在由不同組織維護(hù)的兩個(gè)不同版本的。 showImg(https://segmentfault.com/img/remote/1460000010821004);前面的內(nèi)容大都是關(guān)于 Express 框...
摘要:最近在看,讀完官方的起步教程后想著該自己折騰點(diǎn)東西,就先用實(shí)現(xiàn)一個(gè)超簡(jiǎn)單的,主要記錄下思路。先推薦一個(gè)入門級(jí)的簡(jiǎn)單實(shí)戰(zhàn)項(xiàng)目地址。不過(guò)鑒于初學(xué),自身的思路肯定不會(huì)是最佳實(shí)踐,慢慢積累。 最近在看node.js,讀完官方的起步教程后想著該自己折騰點(diǎn)東西,就先用express + ejs實(shí)現(xiàn)一個(gè)超簡(jiǎn)單的webserver,主要記錄下思路。先推薦一個(gè)nodejs入門級(jí)的簡(jiǎn)單實(shí)戰(zhàn)項(xiàng)目地址。很適合...
摘要:安裝完畢后,打開終端,在終端分別輸入如下命令,檢測(cè)是否安裝成功。號(hào)會(huì)告訴安裝最新版本。它會(huì)為每一條記錄創(chuàng)建一個(gè)唯一的值。注意我們不需要提前創(chuàng)建這個(gè),它會(huì)在第一次使用的時(shí)候自動(dòng)創(chuàng)建。我們可以使用,這是我最常用的方式。 60分鐘學(xué)會(huì)使用Node.js+Express+Ejs+mongoDB 本文出自從零到壹全棧部落 (Node+Vue+微信公眾號(hào)開發(fā))企業(yè)級(jí)產(chǎn)品全棧開發(fā)速成周末班首期班(1...
閱讀 2359·2021-11-24 11:16
閱讀 2043·2021-09-30 09:47
閱讀 2010·2021-09-10 10:51
閱讀 1327·2019-08-30 14:08
閱讀 3145·2019-08-30 13:47
閱讀 1534·2019-08-30 13:02
閱讀 3238·2019-08-29 12:29
閱讀 3203·2019-08-26 17:05