点击通往->黑马node.js视频.
1、实现网站的业务逻辑
2、数据的增删改查
1、使用js语法开发后端应用
2、生态系统活跃,有大量开源库可以使用
3、前端开发工具大多基于Node开发
Node是一个基于Chrome V8引擎的js代码运行环境
运行环境:
1、node.js组成
node.js由两部分组成:ECMAScript(基础语法)+Node模块API
1、js开发的弊端
js在使用时存在两大问题,文件依赖和命题冲突
2、Node.js中模块化开发规范
使用exports对象进行成员导出:
//a.js
//在模块内部定义变量
let version = 1.0;
//在模块内部定义方法
const sayHi = name => `您好,${name}`;
//向模块外部导出数据
exports.version = version;
exports.sayHi = sayHi;
使用require方法导入其他模块:
//b.js
//在b.js模块中导入模块a
let a = require('./a.js');
//输出a模块中的version变量
console.log(a.version);
//调用a模块中的sayHi方法并输出其返回值
console.log(a.sayHi('xiaoyang'));
1、什么是系统模块
node运行环境提供的API。因为这些API都是以模块化的方式进行开发的,所以我们又称为node运行环境提供的API为系统模块
2、fs文件操作
引入fs模块
const fs = require('fs');
(1)为什么要进行路径拼接
(2)路径拼接语法
//语法
path.join('路径一','路径二',...)
1、什么是第三方模块
别人写好的、具有特定功能的、我们可以直接使用的模块即第三方模块,由于通常是由多个文件组成并且被放置在一个文件夹中,所以又名为包
第三方模块有两种存在形式:
2、如何获取第三方模块
npmjs.com:第三方模块的存储和分发仓库
全局安装与本地安装
3、第三方模块nodemon
nodemon是一个命令行工具,用于辅助开发
在Node.js,每次修改文件都要在命令行工具重新执行 改文件,非常繁琐
nrm:npm下载地址切换工具(镜像下载,npmjs.com国外网站)
基于node 平台开发的前端构建工具
将机械化操作编写成任务,想要执行机械化操作时执行一个命令行命令就能自动执行了,用机器代替手工,提高开发效率
(1)Gulp能做什么
(2)使用
(3)gulp提供的方法
(4)gulp插件
1、node_modules文件夹的问题
2、package.json文件的作用
项目描述文件,记录了当前项目的信息,例如项目名称、版本、作者、github地址,当前项目依赖了哪些第三方模块等等,使用npm init -y命令生成
3、项目依赖
在项目的开发阶段和线上运行阶段,都需要依赖的第三方包,称为项目依赖
使用npm install 包命令下载的文件会默认被添加到package.json文件的dependencies字段中
1、模块查找规则-当模块拥有路径但没有后缀时
2、模块查找规则-当模块没有路径且没有后缀时
1、创建web服务器
//引用系统模块http
const http = require('http');
//创建web服务器
const app = http.createServer();
//当客户端发送请求的时候
app.on('request',(req,res)=>{
//响应
res.end('hi,user
');
});
app.listen(3000);
console.log('网站服务器启动成功');
1、http协议的概念
超文本传输协议(http)规定了如何从网站服务器传输超文本到本地浏览器,它基于客户端服务器架构工作,是客户端和服务器端请求和应答的标准
2、报文
在http请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式
3、请求报文
(1)请求方式
(1)http状态码
(2)内容类型
1、请求参数
客户端向服务器端发送请求时,有时候需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端,比如登录操作。
2、GET请求参数
参数被放置在浏览器地址栏中。
3、POST请求参数
路由是指客户端请求地址与服务器端程序代码的对应关系,即请求什么就响应什么
核心代码:
5、静态资源
服务器端不需要处理的,可以直接响应给客户端的资源就是静态资源,例如css、js、image文件
6、动态资源
相同的请求地址不同的响应资源
同步API:只有当前执行完成后,才能执行下一步API
异步API:当前API的执行不会阻塞后续代码的执行
2、同步API和异步API区别
自定义函数让别人去调用
4、node.js中的异步API
5、Promise
Promise出现的目的是解决node.js异步编程中回调地狱的问题
let promise = new Promise((resolve,reject) =>{
setTimeout(() =>{
if(true){
resolve({name:'张三'})
}else{
reject('失败了')
}
},2000);
});
promise.then(result => console.log(result);)
.catch(error =>console.log(error);)
6、异步函数
异步函数是异步编程语法的终极解决方案,它可以让我们将异步代码写成同步的形式,让代码不再有回调函数嵌套,使代码变得清晰明了
数据库即存储数据的仓库,可以将数据进行有序的分门别类的存储。它是独立于语言之外的软件,可以通过API去操作它。
在一个数据库软件中可以包含多个数据库,在每一个数据库仓库中可以包含多个数据集合,每个数据集合可以包含多条文档(具体数据)。
术语 | 解释说明 |
---|---|
database | 数据库,mongoDB数据库软件中可以建立多个数据库 |
collection | 集合,一组数据的集合,可以理解为javascript中的数组 |
document | 文档,一条具体的数据,可以理解为JavaScript中的对象 |
field | 字段,文档中的属性名称,可以理解为JavaScript中的对象属性 |
使用node.js操作MongoDB数据库需要依赖的node.js第三方包mongoose
使用npm install mongoose命令下载
在命令行工具(管理员身份)运行net start mongodb即可以mongodb,否则mongodb无法连接
使用mongoose提供connect方法即可以连接数据库
//引入
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/playground')
.then(()=>console.log('数据库连接成功'))
.catch(err=>console.log('数据库连接失败',err));
在mongodb中不需要显示的创建数据库,如果正在使用的数据库不存在,mongodb会自动创建
创建集合分为两步
创建mongoose.Schema构造函数的实例即可创建集合
语法如下:
//设定集合规则,用Schema
const courseSchema = new mongoose.Schema({
name:String,
author:String,
isPublished:Boolean
});
//创建集合并应用规则
//用mongoose.model创建集合实例,集合名首字母要大写
//这里虽然取得名字是Course,但在数据库中是courses
const Course = mongoose.model('Course',courseSchema);
创建文档实际上就是向集合中插入数据
方法一:
分为两步:
语法如下:
//创建集合实例
const course = new Course({
name: 'node.js',
author: 'hm',
isPublished: true
})
// 调用实例对象下的save方法将数据库保存到数据库中
course.save();
方法二:
用create方法
Course.create({ name: 'es6', author: 'pink', isPublished: false }, (err, result) => {
console.log(err);
console.log(result);
})
和数据库相关的操作都是异步操作
create方法也返回promise对象,所以也可以这样写:
Course.create({ name: 'es6', author: 'pink', isPublished: false })
.then(doc=>console.log(doc))
.catch(err=>console.log(err))
①要查询文档就首先要有足够的数据,所以要先导入数据,语法如下:
mongoimport -d 数据库名称 -c 集合名称 --file 要导入的数据文件
②查询文档
(1)通过find()方法查询
//根据条件查找文档
//find()中语句为空则查找所有文档
Course.find().then(result => console.log(result));
//返回文档集合
当find()中为空时:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/playground')
.then(() => console.log('数据库连接成功'))
.catch(err => console.log('数据库连接失败', err));
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
const Course = mongoose.model('Course', courseSchema);
Course.find().then(result => console.log(result));
将find()中加一个条件{ _id: ‘615aef0b3afad93afa05a9a9’ }:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/playground')
.then(() => console.log('数据库连接成功'))
.catch(err => console.log('数据库连接失败', err));
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
const Course = mongoose.model('Course', courseSchema);
Course.find({ _id: '615aef0b3afad93afa05a9a9' }).then(result => console.log(result));
执行后结果为::
不管find()查找到一条还是0条还是多条数据,返回的都是数组
(2)通过findOne()方法查询
findOne()中为空时,默认返回集合中的第一条数据
Course.findOne().then(result => console.log(result));
findOne()只返回一个数据
(3)匹配大于 小于 包含 查询字段 排序 限制查询
select(’’)中选择要查询的字段,字段前加-号则为不要查询的字段
sort(’’)按照某一字段排序,默认升序,字段前加-号则为降序
skip()跳过多少条数据,limit限制查询数据
①删除单个
Course.findOneAndDelete({条件}).then(result => console.log(result));
查找一条文档并删除
返回删除的文档
如果查询条件匹配了多个文档,那么将会删除第一个匹配的文档
②删除多个
Course.deleteMany({条件}).then(result => console.log(result));
返回结果为删除的个数:
①更新单个
如果多个文档都符合查询条件,那也只修改第一个
Course.updateOne({查询条件},{要修改的值}).then(result => console.log(result));
例如:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/playground')
.then(() => console.log('数据库连接成功'))
.catch(err => console.log('数据库连接失败', err));
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
const Course = mongoose.model('Course', courseSchema);
Course.updateOne({ author: 'pink' }, { name: 'html,css,js' }).then(result => console.log(result));
返回结果(修改成功):
返回结果为一个对象,包含了是否有修改成功的信息
②更新多个
Course.updateMany({查询条件},{要修改的值}).then(result => console.log(result));
例如:
Course.updateMany({},{author: 'pink' }).then(result => console.log(result));
在创建集合规则时,可以设置当前字段的验证规则,验证失败就则输入插入失败。比如设置字符串的长度大于多少小于多少,如果不符合这个要求就验证失败就则输入插入失败。
常用验证规则:
const courseSchema = new mongoose.Schema({
name: {
type: String,
//设置集合规则时,将name字段设置为必传字段
required: true
//也可以这样写:required: [true, '请输入课程名'],报错时会提示‘请输入课程名’
},
author: String,
isPublished: Boolean
});
//设置了required:true后,下面创建文档就会报错
Course.create({ name: '', author: 'pink', isPublished: false }, (err, result) => {
console.log(err);
console.log(result);
})
const courseSchema = new mongoose.Schema({
name: {
type: String,
required: [true, '请输入课程名'],
minlength: [2, '课程名字符串长度请大于2'],
maxlength: [6, '课程名字符串长度请小于6']
},
author: String,
isPublished: Boolean
});
const Course = mongoose.model('Course', courseSchema);
//下面两个创建就会报错
Course.create({ name: 'a', author: 'pink', isPublished: false }, (err, result) => {
console.log(err);
console.log(result);
})
Course.create({ name: 'aaaaaaa', author: 'pink', isPublished: false }, (err, result) => {
console.log(err);
console.log(result);
})
validate:{
validator:v=>{
//返回一个布尔值
//true验证成功
//false验证失败
//v要验证的值
return v && v.length>4
},
//自定义错误信息
message:'传递的值不符合验证信息'
}
获取验证错误信息:
catch(error => {
//获取错误信息对象
const err = error.errors;
//循环错误信息对象
for(var attr in err){
//将错误信息打印到控制台中
console.log(err[attr]['message']);
}
})
通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用的集合关联
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/playground')
.then(() => console.log('数据库连接成功'))
.catch(err => console.log('数据库连接失败', err));
//用户集合规则
const userSchema = new mongoose.Schema({
name: String,
age: Number
});
//文章集合规则
const postSchema = new mongoose.Schema({
title: String,
//使用_id对集合进行关联,ref来连接
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
再创建用户:
User.create({ name: 'hm', age: 23 }).then(result => console.log(result));
再创建文章:
Post.create({ title: '1233', author: '615c1bea7813d054c2a70505' }).then(result => console.log(result));
Post.find()
.populate('author')
.then((result) => console.log(result));
模板引擎是第三方模板
让开发者以更加友好的方式拼接字符串,使项目代码更加清晰,更加易于维护
//导入模板引擎
const template = require('art-template');
const path = require('path');
//将特定模板与特定数据进行拼接
//模板路径 绝对路径
//要在模板中显示的数据 对象类型
//返回拼接好的字符串
const index = path.join(__dirname, 'index.art');
const html = template(index, {
data: {
name: '张三',
age: 20
}
});
console.log(html);
index.art文件:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
{{data.name}}
{{data.age}}
body>
html>
如果数据中携带HTML标签,默认模板引擎不会解析标签,会将其转义后输出
要想原文输出:
//导入模板引擎
const template = require('art-template');
const path = require('path');
const index = path.join(__dirname, 'index.art');
const html = template(index, {
users: [
'zhangsan',
'lisi',
'wangwu'
]
});
console.log(html);
<body>
<ul>
<% for(var i=0 ;i<users.length;i++){ %>
<li>
<%=users[i]%>
li>
<% } %>
ul>
body>
使用子模板可以将网站公共区块(头部,底部)抽离到单独的文件中
例如:
<body>
<% include('./header.art') %>
<%= msg %>
<% include('./footer.art') %>
body>
我是头部
//footer.art文件
我是底部
//导入模板引擎
const template = require('art-template');
const path = require('path');
const index = path.join(__dirname, 'index.art');
const html = template(index, {
msg: '我是首页'
});
console.log(html);
使用模板继承可以将html骨架抽离到单独的文件中,其他页面模板可以继承骨架文件
解决不同文件独有部分:
{{block ‘名称’}}{{/block}}
{{extend ‘文件路径’}}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>骨架title>
{{block 'head'}}{{/block}}
head>
<body>
{{block 'content'}}{{/block}}
body>
html>
{{extend './gujia.art'}}
{{block 'head'}}
<link rel="sdfesff" ,href="custom.css">
{{/block}}
{{block 'content'}}
{{msg}}
{{/block}}
//js文件
//导入模板引擎
const template = require('art-template');
const path = require('path');
const index = path.join(__dirname, 'index.art');
const html = template(index, {
msg: '我是首页'
});
console.log(html);
Express是一个基于Node平台的web应用开发框架,它提供了一系列强大特性,帮助创建各种web应用。
使用 npm install express 命令下载。
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.get('/', (req, res) => {
//send()
//1.send方法内部会检测响应内容的类型
//2.send方法会自动设置http状态码
//3.send方法会自动设置响应的内容类型及编码
res.send('kuangjia');
});
app.get('/list', (req, res) => {
res.send({
name: 'zhangsan',
age: 20
})
});
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
中间件就是一堆方法,可以接收客户端发来的请求、可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理
中间件主要由两部分组成:中间件方法和请求处理函数
中间件方法由express提供,负责拦截请求,请求处理函数由开发人员提供,负责处理函数
可以针对同一个请求设置多个中间件,对同一个请求进行多次处理
默认情况下,请求从上到下依次匹配中间件,一旦匹配成功,终止匹配
可以调用next方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.get('/request', (req, res, next) => {
req.name = 'zhangsan';
next();
})
app.get('/request', (req, res) => {
res.send(req.name)
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
app.use匹配所有的请求方式,可以直接传入请求处理函数,代表接收所有的请求
app.use第一个参数也可以传入请求地址,代表不论什么请求方式,只要这个请求地址就接收这个请求
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.use((req, res, next) => {
console.log('请求走了app.use中间件');
next();
})
app.use('/request', (req, res, next) => {
console.log('请求走了app.use/request中间件');
next();
})
app.get('/list', (req, res) => {
res.send('list')
})
app.get('/request', (req, res, next) => {
req.name = 'zhangsa';
next();
})
app.get('/request', (req, res) => {
res.send(req.name)
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
(1)路由保护,客户端在访问需要登录的页面时,可以先使用中间件判断用户登录状态,用户如果未登录,则拦截请求,直接响应,禁止用户进入需要登录的页面
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.use('/admin', (req, res, next) => {
let isLogin = true;
if (isLogin) {
next();
} else {
res.send('请先登录')
}
});
app.get('/admin', (req, res) => {
res.send('您已经登录')
});
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
(2)网站维护公告,在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,网站正在维护中
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.use((req, res, next) => {
res.send('当前网站正在维护。。。')
})
app.use('/admin', (req, res, next) => {
let isLogin = true;
if (isLogin) {
next();
} else {
res.send('请先登录')
}
});
app.get('/admin', (req, res) => {
res.send('您已经登录')
});
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
(3)自定义404页面
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.use('/admin', (req, res, next) => {
let isLogin = true;
if (isLogin) {
next();
} else {
res.send('请先登录')
}
});
app.get('/admin', (req, res) => {
res.send('您已经登录')
});
app.use((req, res, next) => {
//为客户端响应404状态码以及提示信息
res.status(404).send('当前访问的页面时不存在的');
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
在程序执行的过程中,不可避免的会出现一些无法预料的错误,比如文件读取失败,数据库连接失败,错误处理中间件时一个集中处理错误的地方(同步代码)
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.get('/index', (req, res) => {
//主动抛出一个错误
throw new Error('程序发生了未知错误')
res.send('程序正常执行');
})
//错误处理中间件
//err参数就是上面的错误对象
app.use((err, req, res, next) => {
res.status(500).send(err.message);
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
当程序出现错误时,调用next()方法,并且将错误信息通过参数的形式传递给next()方法,即可触发错误处理中间件(异步代码)
//引入express框架
const express = require('express');
const fs = require('fs');
//创建网站服务器
const app = express();
app.get('/index', (req, res, next) => {
fs.readFile('./demo.text', 'utf-8', (err, result) => {
if (err != null) {
//传递了参数就代表要触发错误处理中间件
next(err);
} else {
res.send(result);
}
})
})
//错误处理中间件
//err参数就是上面的错误对象
app.use((err, req, res, next) => {
res.status(500).send(err.message);
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
在node.js中,异步API的错误信息都是通过回调函数获取的,支持Promise对象的异步API发生错误可以通过catch方法捕获。
异步函数执行如果发生错误如何捕获错误呢?
try catch可以捕获异步函数以及其他同步代码在执行过程中发生的错误信息,但是不能捕获其他类型的API发生的错误
//引入express框架
const express = require('express');
const fs = require('fs');
const promisify = require('util').promisify;
const readFile = promisify(fs.readFile);
//创建网站服务器
const app = express();
app.get('/index', async(req, res, next) => {
try {
await readFile('./aaa.js');
} catch (error) {
next(error);
}
})
//错误处理中间件
//err参数就是上面的错误对象
app.use((err, req, res, next) => {
res.status(500).send(err.message);
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
//用Router()方法创建一个路由对象
const home = express.Router();
//为路由对象匹配请求路径
app.use('/home', home);
//创建二级路由
home.get('/index', (req, res) => {
res.send('欢迎来到博客首页页面')
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
//route/admin.js
const express = require('express');
const admin = express.Router();
admin.get('/index', (req, res) => {
res.send('欢迎来到博客管理页面');
})
module.exports = admin;
//route/home.js
const express = require('express');
const home = express.Router();
home.get('/index', (req, res) => {
res.send('欢迎来到博客首页页面');
})
module.exports = home;
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
const home = require('./route/home');
const admin = require('./route/admin');
app.use('/home', home);
app.use('/admin', admin);
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
Express框架使用req.query即可获取GET参数,框架内部会将GET参数转换为对象并返回
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
app.get('/index', (req, res) => {
//获取get请求参数
res.send(req.query);
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
在浏览器输入如下:
则会响应:
Express中接收post请求参数需要借助第三方包body-parser(目前已被被弃用)
(express 最新版内置了post参数解析,可以直接调用body-parser,不用引入body-parser了,直接app.use(express.urlencoded({extended:false})))
如下:
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
//拦截所有请求
//extended:false 方法内部使用querystring模块处理请求参数的格式
//extended:true 方法内部使用第三方模块qs处理请求参数的格式
app.use(express.urlencoded({ extended: false }))
app.post('/add', (req, res) => {
//接收post请求参数
res.send(req.body)
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
通过表单来从客户端发送post请求:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<form action="http://localhost:3000/add" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit">
form>
body>
html>
提交后响应了获取的post请求参数:
app.use方法疑惑:
app.use方法需要传递一个请求处理函数进去,但是app.use(express.urlencoded({ extended: false }))为什么传递了一个方法的调用呢?
实际上调用的这个方法的返回值也是一个函数,返回的函数正好作为了app.use的参数,例如如下:
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
//传递了一个方法的调用
app.use(fn())
//这个方法的返回值也是一个函数,返回的函数正好作为了app.use的参数
function fn() {
return function(req, res, next) {
console.log(req.method);
next();
}
}
app.get('/', (req, res) => {
res.send('ok')
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
这个方法也可以传参数:
app.use(fn({ a: 1 }))
function fn(obj) {
return function(req, res, next) {
if (obj.a != 1) {
console.log(req.url);
} else {
console.log(req.method);
}
next();
}
}
通过Express内置的express.static可以方便地托管静态文件,例如img,css,js文件等。
app.use(express.static('public');
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
const path = require('path');
//1、告诉express框架使用什么模板引擎渲染什么后缀的模板文件
app.engine('art', require('express-art-template'))
//2、告诉express框架模板存放的位置是什么
app.set('views', path.join(__dirname, 'views'))
//3、告诉express框架模板默认后缀是什么
app.set('view engine', 'art')
app.get('/index', (req, res) => {
res.render('index', {
//render方法:
//1、拼接模板路径
//2、拼接模板后缀
//3、哪个模板和哪个数据进行拼接
//4、将拼接结果响应给了客户端
msg: 'message'
})
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
此时在views中建一个art文件:
{{msg}}
浏览器上在会响应message
//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
const path = require('path');
app.engine('art', require('express-art-template'))
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'art')
//将变量设置到app.locals对象下面,这个数据在所有的模板中都可以获取到
app.locals.users = [{
name: 'zhangsan',
age: 20
}, {
name: 'lisi',
age: 30
}]
app.get('/index', (req, res) => {
res.render('index', {
msg: 'message'
})
})
//监听端口
app.listen(3000);
console.log('网站服务器启动成功');
然后:index.art文件(其他文件也可以访问app.locals对象下的变量):
{{msg}}
<ul>
{{each users}}
<li>
{{$value.name}} {{$value.age}}
li>
{{/each}}
ul>