1. 重点提炼
-
模板引擎
-
pug模板引擎
- 安装pug
- 循环判断
- 混合模式
- 插值表达式
-
nunjucks模板引擎
- koa-nunjucks-2模块的使用
- nunjucks在koa中的使用
- nunjucks使用中的常用语法
-
注意:目前追求静态网页,pug、 nunjucks这种动态网页使用率很小,在录播仅做了解即可。
-
表达式
-
判断语句
-
循环语句
-
宏模式
-
导入导出
2. 模板引擎
模板引擎:模板引擎是web
应用中动态生成html
的工具,负责将数据和模板结合;常见模板引擎有:ejs
、jade
(现更名为pug
)、Handlebars
、Nunjucks
、Swig
等;使用模板引擎可以是项目结构更加清晰,结构更加合理,让项目维护变得更简单;
3. pug模板引擎
-
安装pug
npm i pug -g
-
pug常用语法
- pug语法:通过缩进关系,代替以往html的层级包含关系,如 个简单的静态 可以表达为,注意要统一使用tab或者空格缩进,不要混用
- 内联书写层级,a: img
- style属性:div(style={width:”200px”,color:”red”})
- 使用”-”来定义变量,使用“=”把变量输出到元素内;
- 通过 #{variable} 插 相应的变量值
- html 元素属性通过在标签右边通过括号包含(可以通过判断来添加)
- 文本通过在 字前 添加竖线符号“|”可让 jade 原样输出内容 在html标签标记后 通过空格隔开 本内容 在html标签标记后通过添加引号“.”添加块级文本
- 注释:可以通过双斜杠进 注释,jade有3种注释 式,可以分别对应输出html 注释、 输出html注释、块级html注释
- 循环:each val in [1,2,3]
- 判断语句:”if else” case when default
- mixin:混合模式
- include common/footer.pug 通过include引入外部文件
-
练习工具 hade;
npm i hade -g
3.1 使用koa
npm i koa koa-router koa-views pug -S
安装依赖
const Koa = require("koa");
const Router = require("koa-router"); // 路由
const views = require("koa-views"); // 通过它来加载模版
let app = new Koa();
let router = new Router();
// 将views(模版)加载进来,第一个参数:模版存放位置 第二个参数:配置选项,让其通过pug进行加载
// __dirname 当前目录
app.use(views(__dirname+"/views",{
// 模版引擎通过pug的形式进行加载
map:{
html:"pug"
}
}));
// "/" 获取主页
router.get("/",async ctx=>{
ctx.body = "hello";
});
app.use(router.routes());
app.listen(3000);
node index.js
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.45
Branch: branch02commit description:a0.45(使用koa的pug模版引擎搭建服务)
tag:a0.45
3.2 pug的使用
根据上面的代码,将模版放在views
里,它会自动查找里面的内容。
新建index.pug
,输入“!”
,根据代码提示点击,自动生成pug
的代码(vs code
)。
发现这里的标签都是单标签,那么怎么区分单标签在什么位置闭合呢?
实际通过缩进闭合,即层级关系在pug
里是通过缩进体现的。注意缩进风格需要统一,否则会识别不出来而报错。
但最终渲染后显示在页面上仍旧是html
。
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
body
h1 我是标题
const Koa = require("koa");
const Router = require("koa-router"); // 路由
const views = require("koa-views"); // 通过它来加载模版
let app = new Koa();
let router = new Router();
// 将views(模版)加载进来,第一个参数:模版存放位置 第二个参数:配置选项,让其通过pug进行加载
// __dirname 当前目录
app.use(views(__dirname+"/views",{
map:{
html:"pug"
}
}));
// "/" 获取主页
router.get("/",async ctx=>{
// 渲染,注意渲染是需要时间,它是异步的
await ctx.render("index.pug");
});
app.use(router.routes());
app.listen(3000);
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.46
Branch: branch02commit description:a0.46(pug初次使用)
tag:a0.46
3.3 pug添加标签及样式
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.47
Branch: branch02commit description:a0.47(pug添加标签及样式)
tag:a0.47
3.4 pug标签简写 => 通过class与id
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(直接写class即可,类似css的选择器形式),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.48
Branch: branch02commit description:a0.48(pug标签简写 => 通过class与id)
tag:a0.48
3.5 pug注释
它有两种注释情形:
1、pug注释(只能在pug中看到,渲染到页面中开发者工具是看不到);
2、html注释,但只有html注释会显示在页面中的开发者工具的元素里。
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.49
Branch: branch02commit description:a0.49(pug注释与html注释的使用)
tag:a0.49
3.6 pug默认标签
内容写在下方缩进,之后,默认为当成标签(注意不识别中文。)
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
hello
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.50
Branch: branch02commit description:a0.50(pug默认标签)
tag:a0.50
3.7 pug插入标签内容
但是我们可以通过转义的方式,将其转义为标签内容
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.51
Branch: branch02commit description:a0.51(pug标签中插入内容)
tag:a0.51
3.8 pug变量即差值表达式
pug除了缩进和单标签外特性,还要变量特性。它可以定义变量和循环,相当于做一些js的操作,然而正常的html语言是不支持的。
用-
定义变量,不需要分号。
#{str}
差值表达式,简称表达式。
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.52
Branch: branch02commit description:a0.52(pug变量即差值表达式)
tag:a0.52
3.9 pug从后端获取数据渲染页面
很多情况,这个变量可以从后端推送过来。
const Koa = require("koa");
const Router = require("koa-router"); // 路由
const views = require("koa-views"); // 通过它来加载模版
let app = new Koa();
let router = new Router();
// 将views(模版)加载进来,第一个参数:模版存放位置 第二个参数:配置选项,让其通过pug进行加载
// __dirname 当前目录
app.use(views(__dirname+"/views",{
map:{
html:"pug"
}
}));
// "/" 获取主页
router.get("/",async ctx=>{
// 渲染,注意渲染是需要时间,它是异步的
await ctx.render("index.pug",{
data:"我是数据",
});
});
app.use(router.routes());
app.listen(3000);
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.53
Branch: branch02commit description:a0.53(pug从后端获取数据渲染页面)
tag:a0.53
3.10 pug获取后端的数组
后端不仅可以推送一个变量,还可以推送多个变量(最常见则是对象数组)。
const Koa = require("koa");
const Router = require("koa-router"); // 路由
const views = require("koa-views"); // 通过它来加载模版
let app = new Koa();
let router = new Router();
// 将views(模版)加载进来,第一个参数:模版存放位置 第二个参数:配置选项,让其通过pug进行加载
// __dirname 当前目录
app.use(views(__dirname+"/views",{
map:{
html:"pug"
}
}));
// "/" 获取主页
router.get("/",async ctx=>{
// 渲染,注意渲染是需要时间,它是异步的
let users = [{
name:"张三",age:20,height:"178cm"},{
name:"李四",age:25,height:"179cm"},{
name:"王五",age:26,height:"180cm"}]
await ctx.render("index.pug",{
data:"我是数据",
users
});
});
app.use(router.routes());
app.listen(3000);
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
ul
// 通过each循环
each item,index in users
li 姓名是:#{item.name};年龄是:#{item.age};身高是:#{item.height};索引是:#{index}
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.54
Branch: branch02commit description:a0.54(pug获取后端的数组)
tag:a0.54
3.11 pug => for循环
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
ul
// 通过each循环
each item,index in users
li 姓名是:#{item.name};年龄是:#{item.age};身高是:#{item.height};索引是:#{index}
- for(let i=0;i<4;i++)
br
span 我是循环出来的数据#{i}
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.55
Branch: branch02commit description:a0.55(pug => for循环)
tag:a0.55
3.12 pug => case…when
并且还拥有类似js的switch…case… 但在这里是case…when
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
ul
// 通过each循环
each item,index in users
li 姓名是:#{item.name};年龄是:#{item.age};身高是:#{item.height};索引是:#{index}
- for(let i=0;i<4;i++)
br
span 我是循环出来的数据#{i}
- let num = 1
case num
when 1
p num 是一
when 2
p num 是二
default
p num 是其他值
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.56
Branch: branch02commit description:a0.56(pug => case…when)
tag:a0.56
3.13 mixin
除了这些还有一些不一样的操作,比如混入模式/混合模式(mixin
<宏>):比如在pug里面可以定义很多函数,然后可以进行使用。它通过“+”
进行调用。如遇到经常常用的东西,就可以定义为模版,即这里的函数,在pug里调用,非常方便。
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
ul
// 通过each循环
each item,index in users
li 姓名是:#{item.name};年龄是:#{item.age};身高是:#{item.height};索引是:#{index}
- for(let i=0;i<4;i++)
br
span 我是循环出来的数据#{i}
- let num = 1
case num
when 1
p num 是一
when 2
p num 是二
default
p num 是其他值
mixin mydiv
div 我是非常常用的div
+mydiv
+mydiv
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.57
Branch: branch02commit description:a0.57(pug => mixin使用)
tag:a0.57
同样函数功能也可以稍微复杂一些,如传参。
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
ul
// 通过each循环
each item,index in users
li 姓名是:#{item.name};年龄是:#{item.age};身高是:#{item.height};索引是:#{index}
- for(let i=0;i<4;i++)
br
span 我是循环出来的数据#{i}
- let num = 1
case num
when 1
p num 是一
when 2
p num 是二
default
p num 是其他值
mixin mydiv
div 我是非常常用的div
+mydiv
+mydiv
mixin pet(name,sex)
p 这是一只#{name};它的性别是#{sex}
+pet("狗狗","公")
+pet("猫","母")
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.58
Branch: branch02commit description:a0.58(pug => mixin传参)
tag:a0.58
3.14 自定义模版
以及pug里还可定义一些常用模版,比如设计一个common.pug
h2 我是公共模板
引入公共模版
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
ul
// 通过each循环
each item,index in users
li 姓名是:#{item.name};年龄是:#{item.age};身高是:#{item.height};索引是:#{index}
- for(let i=0;i<4;i++)
br
span 我是循环出来的数据#{i}
- let num = 1
case num
when 1
p num 是一
when 2
p num 是二
default
p num 是其他值
mixin mydiv
div 我是非常常用的div
+mydiv
+mydiv
mixin pet(name,sex)
p 这是一只#{name};它的性别是#{sex}
+pet("狗狗","公")
+pet("猫","母")
include common.pug
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.59
Branch: branch02commit description:a0.59(自定义模版)
tag:a0.59
3.15 引入js
<!DOCTYPE html>
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
style.
.mydiv{
width:200px;
height:200px;
background:red;
}
body
h1 我是标题
div 我是div
div(class="mydiv") 我是类名为mydiv的div
br
span 我是span
//- div 简写形式(class),style属性值是类js环境,以对象方式
.mydiv2(style={width:"100px",height:"100px",background:"blue"}) 我是div2
//- div 简写形式(id)
#myid 我是id为myid的div
//- 我是pug注释
//-
我是第一行
我是第二行
// 我是html注释
//
我是第一行
我是第二行
div
| hello
- let str = "你好"
p #{str}
p #{data}
ul
// 通过each循环
each item,index in users
li 姓名是:#{item.name};年龄是:#{item.age};身高是:#{item.height};索引是:#{index}
- for(let i=0;i<4;i++)
br
span 我是循环出来的数据#{i}
- let num = 1
case num
when 1
p num 是一
when 2
p num 是二
default
p num 是其他值
mixin mydiv
div 我是非常常用的div
+mydiv
+mydiv
mixin pet(name,sex)
p 这是一只#{name};它的性别是#{sex}
+pet("狗狗","公")
+pet("猫","母")
include common.pug
script(type="text/javascript").
console.log(1111);
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.60
Branch: branch02commit description:a0.60(引入js)
tag:a0.60
4. nunjucks模板引擎在koa中的应用
pug对于html语法来说不是太友好,对缩进和单标签很不适应,nunjucks会更友好。
-
安装koa-nunjucks-2
-
使用nunjucks
const nunjucks = require('koa-nunjucks-2'); app.use(nunjucks({ ext:"html", //指定模板后缀 path:path.join(__dirname,'views'), //指定视图目录 nunjucksConfig:{ trimBlocks:true //开启转义,防止xss漏洞 } }))
-
推荐使用”.njk“后缀名
-
nunjucks的语法使用
-
变量:
{ {username}}
-
注释:
{ # Loop through all the users #}
-
if
{ % if hungry %} I am hungry { % elif tired %} I am tired { % else %} I am good! { % endif %}
-
for
<h1>Posts</h1> <ul> { % for item in items %} <li>{ { item.title }}</li> { % else %} <li>This would display if the 'item' collection were empty</li> { % endfor %} </ul>
-
过滤器
{ { foo | replace("foo", "bar") | capitalize }}
-
模板继承block/extends
-
定义父类模板
<h1>我是公共模板</h1> <div class="leftContent"> { % block left %} 这边是左侧的内容 { % endblock %} { % block right %} 这边是右侧的内容 { % endblock %} { % block somevalue %} 我是一些数据 { % endblock %} </div>
-
继承父类模板
{ % extends "common.html" %} { % block left %} 我是左侧的内容1111 { % endblock %} { % block right %} 我是右侧的内容11111 { % endblock %} { % block somevalue %} { { super() }} { % endblock %}
-
-
Macro(宏标签)可以定义可复用的内容,类似与编程语言中的函数
- 定义
{ % macro pet(animalName,name="小白") %} <div> 这里是一只{ { animalName}};他的名字是{ { name}} </div> { % endmacro %}
-
调用
{ { pet("狗狗")}}
-
include/import
-
include 引入文件
{ % include "footer.html" %}
-
import 导入文件
- 定义
{ % macro pet(animalName) %} <p>这是一只{ { animalName}}</p> { % endmacro %} { % macro book(bookName) %} <p>这是一本书,名字叫{ { bookName}}</p> { % endmacro %}
-
调用
{ % import 'somemodule.html' as fn %} { { fn.pet("狗狗")}} { { fn.book("nodejs从入门到实践")}}
-
-
4.1 配置koa服务
npm install koa-nunjucks-2 -g
npm i koa koa-router koa-nunjucks-2 -S
const Koa = require("koa");
const Router = require("koa-router");
const nunjucks = require("koa-nunjucks-2");
let app = new Koa();
let router = new Router();
// 使用nunjucks,首先需要配置
app.use(nunjucks({
ext:"html", //后缀名设置,官方推荐后缀名.njk(方便区分)
path:__dirname+"/views", // 模版目录
nunjucksConfig:{
trimBlocks:true //防止Xss(以前常见的攻击网站方式,如在input框写script代码)漏铜;
}
}))
router.get("/",async ctx=>{
ctx.body = "hello";
})
app.use(router.routes())
app.listen(8000);
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.61
Branch: branch02commit description:a0.61(配置nunjucks的koa服务)
tag:a0.61
4.2 使用koa中的nunjucks
const Koa = require("koa");
const Router = require("koa-router");
const nunjucks = require("koa-nunjucks-2");
let app = new Koa();
let router = new Router();
// 使用nunjucks,首先需要配置
app.use(nunjucks({
ext:"html", //后缀名,官方推荐后缀名.njk(方便区分)
path:__dirname+"/views", // 模版目录
nunjucksConfig:{
trimBlocks:true //防止Xss(以前常见的攻击网站方式,如在input框写script代码)漏铜;
}
}))
router.get("/",async ctx=>{
// ext已经设置后缀名了,这里就不需要重复再加后缀了
await ctx.render("index");
})
app.use(router.routes())
app.listen(8000);
nunjucks\views\index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
</body>
</html>
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.62
Branch: branch02commit description:a0.62(使用koa中的nunjucks)
tag:a0.62
4.3 nunjucks使用
nunjucks支持html,区别在于它给html增加了判断、循环、变量等,让html更加丰富多彩,呈现数据会非常方便。
差值表达式{
{xxx}}
,与pug一样。
html注释与html语法一致。nunjucks注释{# 我是nunjucks注释 #}
注意:只修改模版html文件,nodemon是无法监测到的,它只能监测index.js发生的变化,因此需要重启。
判断语句通过%
来写
注意循环和判断结束,一定要写结束标志{% endif %}
。
后端:
const Koa = require("koa");
const Router = require("koa-router");
const nunjucks = require("koa-nunjucks-2");
let app = new Koa();
let router = new Router();
// 使用nunjucks,首先需要配置
app.use(nunjucks({
ext:"html", //后缀名,官方推荐后缀名.njk(方便区分)
path:__dirname+"/views", // 模版目录
nunjucksConfig:{
trimBlocks:true //防止Xss(以前常见的攻击网站方式,如在input框写script代码)漏铜;
}
}))
router.get("/",async ctx=>{
// ctx.body = "hello";
// ext已经设置后缀名了,这里就不需要重复再加后缀了
await ctx.render("index",{
username:"张三",
num:3
});
})
app.use(router.routes())
app.listen(8000);
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
<p>用户名是:{
{username}}</p>
<!-- 我是注释 -->
{# 我是nunjucks注释 #}
{% if num>3 %}
<p>num值大于三</p>
{% elseif num<3 %}
<p>num值小于三</p>
{% else %}
<p>num值等于三</p>
{% endif %}
</body>
</html>
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.63
Branch: branch02commit description:a0.63(nunjucks使用)
tag:a0.63
4.4 循环
除了判断语句,还有循环语句。
后端:
const Koa = require("koa");
const Router = require("koa-router");
const nunjucks = require("koa-nunjucks-2");
let app = new Koa();
let router = new Router();
// 使用nunjucks,首先需要配置
app.use(nunjucks({
ext:"html", //后缀名,官方推荐后缀名.njk(方便区分)
path:__dirname+"/views", // 模版目录
nunjucksConfig:{
trimBlocks:true //防止Xss(以前常见的攻击网站方式,如在input框写script代码)漏铜;
}
}))
router.get("/",async ctx=>{
await ctx.render("index",{
username:"张三",
num:2,
arr:[{
name:"张三",
age:20
},{
name:"李四",
age:28
}]
});
})
app.use(router.routes())
app.listen(8000);
前端:
注意循环末尾一定要有结束符。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
<p>用户名是:{
{username}}</p>
<!-- 我是注释 -->
{# 我是nunjucks注释 #}
{% if num>3 %}
<p>num值大于三</p>
{% elseif num<3 %}
<p>num值小于三</p>
{% else %}
<p>num值等于三</p>
{% endif %}
<ul>
{% for item in arr %}
<li>姓名是:{
{item.name}};年龄是:{
{item.age}};</li>
{% endfor %}
</ul>
</body>
</html>
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.64
Branch: branch02commit description:a0.64(nunjucks使用-for循环)
tag:a0.64
4.5 过滤器
同时还会提供内置的过滤器(类似Vue的过滤器),更多的可参考官网:
后端:
const Koa = require("koa");
const Router = require("koa-router");
const nunjucks = require("koa-nunjucks-2");
let app = new Koa();
let router = new Router();
// 使用nunjucks,首先需要配置
app.use(nunjucks({
ext:"html", //后缀名,官方推荐后缀名.njk(方便区分)
path:__dirname+"/views", // 模版目录
nunjucksConfig:{
trimBlocks:true //防止Xss(以前常见的攻击网站方式,如在input框写script代码)漏铜;
}
}))
router.get("/",async ctx=>{
// ctx.body = "hello";
// ext已经设置后缀名了,这里就不需要重复再加后缀了
await ctx.render("index",{
username:"张三",
num:2,
arr:[{
name:"张三",
age:20
},{
name:"李四",
age:28
}],
str:"hello world"
});
})
app.use(router.routes())
app.listen(8000);
前端:
replace
替换对应字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
<p>用户名是:{
{
username}}</p>
<!-- 我是注释 -->
{
# 我是nunjucks注释 #}
{
% if num>3 %}
<p>num值大于三</p>
{
% elseif num<3 %}
<p>num值小于三</p>
{
% else %}
<p>num值等于三</p>
{
% endif %}
<ul>
{
% for item in arr %}
<li>姓名是:{
{
item.name}};年龄是:{
{
item.age}};</li>
{
% endfor %}
</ul>
{
{
str | replace("world","世界")}}
</body>
</html>
内置过滤器还可以连写功能,比如增加首字母大写:
capitalize 首字母大写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
<p>用户名是:{
{username}}</p>
<!-- 我是注释 -->
{# 我是nunjucks注释 #}
{% if num>3 %}
<p>num值大于三</p>
{% elseif num<3 %}
<p>num值小于三</p>
{% else %}
<p>num值等于三</p>
{% endif %}
<ul>
{% for item in arr %}
<li>姓名是:{
{item.name}};年龄是:{
{item.age}};</li>
{% endfor %}
</ul>
{
{str | replace("world","世界") | capitalize}}
</body>
</html>
注意nodemon识别不了html变化,需要重启nodemon。
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.65
Branch: branch02commit description:a0.65(nunjucks使用-过滤器)
tag:a0.65
4.6 继承
Nunjucks比pug多一些功能,它的模版这块可以实现继承,通过block定义名称。
parent.html
<div>
<p>我是父级模板</p>
{% block left %}
<p>左边内容</p><br>
{% endblock %}
{% block right %}
右边内容
{% endblock %}
</div>
son1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- 继承模版 -->
{% extends 'parent.html' %}
<!-- 替换模版内容 -->
{% block left %}
我是son1里左侧内容
{% endblock %}
{% block right %}
我是son1里右侧侧内容
{% endblock %}
</body>
</html>
后端
const Koa = require("koa");
const Router = require("koa-router");
const nunjucks = require("koa-nunjucks-2");
let app = new Koa();
let router = new Router();
// 使用nunjucks,首先需要配置
app.use(nunjucks({
ext:"html", //后缀名,官方推荐后缀名.njk(方便区分)
path:__dirname+"/views", // 模版目录
nunjucksConfig:{
trimBlocks:true //防止Xss(以前常见的攻击网站方式,如在input框写script代码)漏铜;
}
}))
router.get("/",async ctx=>{
// ctx.body = "hello";
// ext已经设置后缀名了,这里就不需要重复再加后缀了
// await ctx.render("index",{
// username:"张三"
// });
await ctx.render("index",{
username:"张三",
num:2,
arr:[{
name:"张三",
age:20
},{
name:"李四",
age:28
}],
str:"hello world"
});
})
// 再加一个路由
router.get("/son1",async ctx=>{
await ctx.render("son1");
})
app.use(router.routes())
app.listen(8000);
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.66
Branch: branch02commit description:a0.66(nunjucks使用-继承)
tag:a0.66
注意:继承变量名称得一致
son1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- 继承模版 -->
{% extends 'parent.html' %}
{% block left1 %}
我是son1里左侧内容
{% endblock %}
{% block right1 %}
我是son1里右侧侧内容
{% endblock %}
</body>
</html>
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.67
Branch: branch02commit description:a0.67(nunjucks使用-继承变量名称不一致,生成模版默认内容)
tag:a0.67
以上是把son1的内容传到模版parent里,同样也可以把父级的内容拿到子级来使用。
parent.html
<div>
<p>我是父级模板</p>
{% block left %}
<p>左边内容</p>
{% endblock %}
{% block right %}
右边内容
{% endblock %}
{% block somevalue %}
一些数据
{% endblock %}
</div>
son1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- 继承模版 -->
{% extends 'parent.html' %}
{% block left %}
我是son1里左侧内容
{% endblock %}
{% block right %}
我是son1里右侧侧内容
{% endblock %}
<!-- 使用父级的内容 -->
{% block somevalue %}
{
{super()}}
{% endblock %}
</body>
</html>
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.68
Branch: branch02commit description:a0.68(nunjucks使用-把父级的内容拿到子级来使用。)
tag:a0.68
4.7 macro:宏标签
macro:宏标签 => pug中的mixin
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
<p>用户名是:{
{username}}</p>
<!-- 我是注释 -->
{# 我是nunjucks注释 #}
{% if num>3 %}
<p>num值大于三</p>
{% elseif num<3 %}
<p>num值小于三</p>
{% else %}
<p>num值等于三</p>
{% endif %}
<ul>
{% for item in arr %}
<li>姓名是:{
{item.name}};年龄是:{
{item.age}};</li>
{% endfor %}
</ul>
{
{str | replace("world","世界") | capitalize}}
<!-- macro:宏标签 -->
<!-- 定义了一个pet函数 -->
{% macro pet(name='mm',sex='m') %}
<p>我是一只{
{name}},我的性别是{
{sex}}</p>
{% endmacro %}
<!-- 调用 -->
{
{pet("小狗","公")}}
{
{pet()}}
</body>
</html>
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.69
Branch: branch02commit description:a0.69(nunjucks使用-macro:宏标签)
tag:a0.69
4.8 include
其实和pug的混合模式有些类似。=> pug include
同时也可以设置默认参数。注意这里的默认参数和我们平时语言中的不一样,设置了默认值,这个参数就不能传值了。
同时和pug一样,也有include的功能:
footer.html
<h1>我是公共底部</h1>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
<p>用户名是:{
{username}}</p>
<!-- 我是注释 -->
{# 我是nunjucks注释 #}
{% if num>3 %}
<p>num值大于三</p>
{% elseif num<3 %}
<p>num值小于三</p>
{% else %}
<p>num值等于三</p>
{% endif %}
<ul>
{% for item in arr %}
<li>姓名是:{
{item.name}};年龄是:{
{item.age}};</li>
{% endfor %}
</ul>
{
{str | replace("world","世界") | capitalize}}
<!-- macro:宏标签 -->
<!-- 定义了一个pei函数 -->
{% macro pet(name="狗狗",sex) %}
<p>我是一只{
{name}},我的性别是{
{sex}}</p>
{% endmacro %}
<!-- 调用 -->
{
{pet("小狗","公")}}
{
{pet("公")}}
{
{pet("小猫","公")}}
{% include 'footer.html' %}
</body>
</html>
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.70
Branch: branch02commit description:a0.70(nunjucks使用-include)
tag:a0.70
4.9 import
同时还有import,可以引入函数(macro),数量不限。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是标题</h1>
<p>用户名是:{
{username}}</p>
<!-- 我是注释 -->
{# 我是nunjucks注释 #}
{% if num>3 %}
<p>num值大于三</p>
{% elseif num<3 %}
<p>num值小于三</p>
{% else %}
<p>num值等于三</p>
{% endif %}
<ul>
{% for item in arr %}
<li>姓名是:{
{item.name}};年龄是:{
{item.age}};</li>
{% endfor %}
</ul>
{
{str | replace("world","世界") | capitalize}}
<!-- macro:宏标签 -->
<!-- 定义了一个pei函数 -->
{% macro pet(name="狗狗",sex) %}
<p>我是一只{
{name}},我的性别是{
{sex}}</p>
{% endmacro %}
{% macro person(name="小明",sex) %}
<p>我是{
{name}},我的性别是{
{sex}}</p>
{% endmacro %}
<!-- 调用 -->
{
{pet("小狗","公")}}
{
{pet("公")}}
{
{pet("小猫","公")}}
{% include 'footer.html' %}
</body>
</html>
import.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
{% import 'index.html' as obj %}
{
{obj.pet("公")}}
{
{obj.person("男")}}
</body>
</html>
追加路由
router.get("/import",async ctx=>{
await ctx.render("import");
})
参考:https://github.com/6xiaoDi/blog-nodejs-novice/tree/a0.71
Branch: branch02commit description:a0.71(nunjucks使用-import)
tag:a0.71
(后续待补充)