【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.ejs 和 content.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 博客中用了nunjucks 的Custom Tag,但是大部分这个又能简单用函数方法解决,类似的想到。ejs这类后端模版用途还挺多的,比如还能生成构建脚本呀,生成模版项目呀,所以记录一下这个新的ejs的使用方法。
关于生成的时候,不要都用ejs模版去生成,有时候,直接用一个函数突出字符串就行,然后输出到对应的文件即可,ejs那种还是适合相对比较复杂的场景。
四、Hexo专栏
目前 Hexo
系列形成了一个小专栏,欢迎读者继续阅读: Hexo专栏地址