发布于 

【hexo专栏】从hexo联想ejs的模版新用法

ejs 模版,作为 NodeJs 开发者常用的后端模版引擎之一。平常的用法往往是类似这样的代码:
1
2
3
<% if (user) { %>
<h2><%= user.name %></h2>
<% } %>

这个写法是最常写的,相当于是模版去加上对应的js逻辑。

一、关于为什么有这个想法

作为一个 JavaScript 工程师,又因为有字符串模版,那喜欢使用下面这样的形式

1
2
3
4
5
6
7
<% function ProductItemRender(data){
return `<div>
<span>${data.title}</span>
<span>price: ${data.price}</span>
</div>`
}%>
<%- ProductItemRender(data) %>

那我想的是,能不能把这些抽离成一个更方便的。

1
<%- _tag.ProductItemRender(data) %>

相当于能不能有一个组件库,直接调用这样的一个组件库,就能将对应的内容进行输出。

这样,平常有的一些前端模版,就能在服务端类似的套用了,假设购买了一个好看的前端主题,直接将其变成一个方法,将其中的坑位变成函数的参数。

二、如何去实现

2.1 初稿

首先前面已经讲了一种方法,就是在我们的 ejs模版 最开头,加上这样的方法:

1
2
3
4
5
6
7
<% function ProductItemRender(data){
return `<div>
<span>${data.title}</span>
<span>price: ${data.price}</span>
</div>`
}%>
<%- ProductItemRender(data) %>

但是这个有个问题,假设平常我们常用的下面这样的写法:

index.ejs:

1
2
3
4
5
6
7
8
<html>
<head>
</head>
<body>
<%- include('./header.ejs') %>
<%- include('./content.ejs') %>
</body>
</html>

然后我们假设在 header.ejscontent.ejs 里面都调用组件,难道要在每个文件的开头写上这个组件函数,那太麻烦了。

2.2 升级方案

通过在 ejs.compile 的函数调用的地方下手:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const viewPath = path.join(__dirname, 'view');
const cache = {};

const render = (filename, data={}) =>{
if(!cache[filename]){
cache[filename] = (data)=>{
let filePath = path.join(viewPath, filename);
let func = ejs.compile(fs.readFileSync(filePath), {
root: viewPath,
filename: filePath,
cache: true
});
return func(Object.assign({}, data, {
_tag: {
ProductItemRender: (data)=>{
return `<div>
<span>${data.title}</span>
<span>price: ${data.price}</span>
</div>`
}
}
}))
};
}
return cache[filename](data);
}

这样模版里面就能直接用

1
<%- _tag.ProductItemRender(data) %>

而且网上找的非SPA的那类网站,可以非常简单的套用模版,做出好看的网站。无非就是把那段html变成一个函数的返回值吐出。

三、小结

本文是作为一个小技巧,因为看到 hexo 博客中用了nunjucksCustom Tag,但是大部分这个又能简单用函数方法解决,类似的想到。ejs这类后端模版用途还挺多的,比如还能生成构建脚本呀,生成模版项目呀,所以记录一下这个新的ejs的使用方法。

关于生成的时候,不要都用ejs模版去生成,有时候,直接用一个函数突出字符串就行,然后输出到对应的文件即可,ejs那种还是适合相对比较复杂的场景。

四、Hexo专栏

目前 Hexo 系列形成了一个小专栏,欢迎读者继续阅读: Hexo专栏地址


如果你有什么意见和建议,可以点击: 反馈地址 进行反馈。