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