Node.js,es6中的异步和同步promise,还有数据库mongoDB的基础使用

node.js

  1. 编程运行环境
  2. 模块化开发
  3. exports对象导出,使用require方法引入
  4. 并且导入的文件名的后缀可以省略
  5. 使用module.exports.obj 导出模块成员
  6. exports 和module.exports指向不同的对象时 最终以后者为准

系统模块

  1. f:file s:syetem
  2. fs.reaFile(‘文件路径’[,’文件编码’],callback) 读取方法

查看答案

1
2
3
4
5
6
7
8
9
// 通过模块的名字
const fs = require('fs')
fs.readFile('./c.js', 'utf8', (err, doc) => {
// console.log(err);
// console.log(doc);
if(err ==null){
console.log(doc);
}
})
  1. 文件写入内容 fs.writeFile(‘文件路径’,’数据’,callback)

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 通过模块的名字
const fs = require('fs');
fs.readFile('./c.js', 'utf8', (err, doc) => {
// console.log(err);
// console.log(doc);
if (err == null) {
// console.log(doc);
// 将另一个文件中获取的数据导入到指定的文件夹中
fs.writeFile('./write.js', doc, err => {
if(err == null){
console.log('写入文件成功');
}else{
console.log(`写入文件失败${err}`);
}

} )
}
})
  1. path路径操作 path.join(‘路径’,’路径’, …)

    查看答案

    1
    2
    3
    4
    const path = require('path')

    let a = path.join('public','uploads','avatar')
    console.log(a);
  2. 相对路径绝对路径,使用__dirname获取当前的绝对路径用于数据合并

第三方模块

  1. npm install/ uninstall 模块名称
  2. 安装淘宝源淘宝源

gulp模块

  1. gulp.src() 获取任务要处理的文件
  2. gulp.dest() 输出文件
  3. gulp.task() 建立gulp任务
  4. gulp.watch() 监控文件的变化

gulp实例

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// 引用gulp
const gulp = require('gulp')
const path = require('path') // 获取环境
const htmlmin = require('gulp-htmlmin') // 压缩html
const fileinclude = require('gulp-file-include'); // 抽取公共的部分
const less = require('gulp-less'); //将less文件转化
const cssMin = require('gulp-css'); //压缩css
const jsmin = require('gulp-jsmin'); // 压缩js
const rename = require('gulp-rename'); //可以省略这是一个重新命名的操作
const babel = require('gulp-babel');
const uglify = require('gulp-uglify'); // 第二种压缩方法
// 执行命令
gulp.task('first', dnoe => {
console.log('人生中第一个gulp命令');
// 获取文件
gulp.src('./src/css/style.css')
// 压缩文件
.pipe(gulp.dest('dist/css'))
dnoe()
})

// html 任务 压缩文件,将公共代码抽取

gulp.task('htmlmin', done => {
gulp.src('./src/*.html')
.pipe(fileinclude({
prefix: '@@',
basepath: '@file'
})) // 抽取公共部分
// 压缩html文件的代码
.pipe(htmlmin({ collapseWhitespace: true }))
.pipe(gulp.dest('dist'));
done()
})

// css压缩 less格式转化
// 第一种
// gulp.task('lesscss',() =>{
// gulp.src('./src/css/*.less')
// .pipe(less({
// paths: [ path.join(__dirname, 'less', 'includes') ]
// }))
// .pipe(gulp.dest('./src/css'));
// gulp.src('./src/css/*.css')
// .pipe(cssMin())
// .pipe(gulp.dest('./dist/css'))
// })

// 第二种方法

gulp.task('cssless', done => {
gulp.src(['./src/css/*.less', './src/css/*.css']) // 先将less文件转化为css,在进行压缩
.pipe(less({
paths: [path.join(__dirname, 'less', 'includes')]
}))
.pipe(cssMin())
.pipe(gulp.dest('./dist/css'))
done()
})
// 将js代码压缩 第一种 将js代码从es6转化为es5
gulp.task('jsmin', done => {
gulp.src('./src/js/*.js')
.pipe(jsmin())
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest('./dist/js/'))
done()
})
// 第二种转化后压缩
gulp.task('jsmm', done => {
gulp.src('./src/js/*.js')
.pipe(babel({
presets: ['@babel/env']
}))
.pipe(uglify())
.pipe(gulp.dest('./dist/js/'))
done()
})
// 构建任务
// gulp.task('default',['first','htmlmin','cssless','jsmin','jsmm'])
gulp.task('build', gulp.parallel('first', 'htmlmin', 'cssless', 'jsmin', 'jsmm'));

node_modules文件夹问题

  1. 项目依赖 dependencies 使用命令 npm install --production
  2. 开发依赖 加--save-dev命令 将包添加到package
  3. package-lock.json 锁定包的版本,加快包的下载速度
  4. 别名的用法 在script中加入一个build,nodemon xx.js
  5. npm init -y 生成包

require查找规则

先找文件=>文件夹=>找package.json 中的main选项
如果直接写require(‘xx’) 默认先查找系统模块 node_modules

服务器端

  1. http 超文本协议,提供了一种发布和接受HTML页面的方法
  2. 传输协议://服务器ip或者域名:端口/资源所在的位置

创建web服务器

  1. 用于协议,创建对象req,res ,监听端口

    查看答案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 创建网址服务器模块
    const http = require('http')
    // 网站服务器的对象
    const app = http.createServer()
    // 当客户端有请求来的时候
    app.on('request',(req,res)=>{
    res.end('<h2>hello user</h2>')
    })
    app.listen(3000)
    console.log('网站服务器启动成功');
  2. http 协议

  3. 报文 请求或者响应过程中传递的数据块

  4. 请求报文 get 请求数据 post发送请求

  5. req.url 获取请求地址

  6. req.header 获取请求报文

  7. res.writeHead 设置响应状态码

响应报文

  1. 200 请求成功
  2. 404 请求的资源没有被找到
  3. 500 服务器端错误
  4. 400 客服端请求有语法错误

post参数

  1. 获取psot参数需要使用data和end事件
  2. 使用querystring系统模块将参数转化为对象的形式

查看答案

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 创建网址服务器模块
const http = require('http')
// 用于处理url地址
const url = require('url')
// 网站服务器的对象
const app = http.createServer()
// 当客户端有请求来的时候
app.on('request',(req,res)=>{
// 自定义响应状态码
res.writeHead(200,{
// 设置响应信息
'content-type':'text/html;charset=utf8'
})
// 第一参数要解析的url地址,第二个参数是将查询参数解析成对象的形式
let {query,pathname} = url.parse(req.url, true)
console.log(query.name);
console.log(query.age);
// 解析的url地址
console.log(req.url);
// 获取请求地址
console.log(req.headers['accept']); // 获取请求报文
if(pathname == '/index' || pathname == '/'){
res.end('<h2>welcome to index,欢迎来到我的主页</h2>')
}else{
res.end('not found')
}
// if(req.url == '/index' || req.url == '/'){
// res.end('<h2>welcome to index,欢迎来到我的主页</h2>')
// }else{
// res.end('not found')
// }
console.log(req.method)
// if(req.method=='POST'){
// res.end('post')
// }else{
// res.end('get')
// }
})
app.listen(3000)
console.log('网站服务器启动成功');

查看答案

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 http = require('http')
// 用于处理url地址
const url = require('url')
// 网站服务器的对象
const app = http.createServer()
// 将提交的信息转化为对象
const querystring = require('querystring')
// 当客户端有请求来的时候
app.on('request',(req,res)=>{
// post参数是通过事件的方式接受的
// data 当请求参数传递的时候发出data事件
// end 当参数传输完成时发出end事件
let postParams = ''
req.on('data', params =>{
postParams += params
})
req.on('end',()=>{
console.log(querystring.parse(postParams));
// console.log(postParams);
})
res.end('ok')

})
app.listen(3000)
console.log('网站服务器启动成功');

https请求与响应处理

  1. 静态资源

查看答案

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
27
28
29
30
31
32
33
34
35
36
37
38
39
const http = require('http')

const app = http.createServer()

const path = require('path')
const fs =require('fs')
const url = require('url')
// 使用第三方模块来自动判断请求路径分析出请求类型
const mime =require('mime')
app.on('request', (req, res) => {
// 获取用户输入的路径

let pathname = url.parse(req.url).pathname
// 判断开始时的页面访问情况
pathname = pathname == '/' ? '/index.html' : pathname
// 获取文件的绝对路 获取系统的真实路径
let realname = path.join(__dirname,'public' + pathname)
// mime
let type = mime.getType(realname)
console.log(type);
// 读取文件
fs.readFile(realname,(error,result) =>{
// 读取失败响应给客服端
if(error != null){
res.writeHead(404,{
'content-type':'text/html;charset=utf8'
})
res.end('文件读取失败')
return
}
res.writeHead(200,{
'content-type': type
})
res.end(result)
})

})
app.listen(1000)

  1. 动态资源

同步API 异步API

  1. 异步API不会阻塞之后的程序,默认返回undefined
  2. 回调函数来获取异步的返回值,自己调用自己

查看答案

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// function getData(callback){
// callback('213')
// }
// getData(function(n){
// console.log('callback函数被调用了');
// console.log(n);
// // })
// for(var i = 0;i<1000;i++){
// console.log(i);
// }
// // 同步会组测后面代码的执行
// console.log('for循环后的代码');
// 异步api不会等到api执行完成后在向下执行代码

// console.log('代码开始执行');
// // 定时器属于异步API
// setTimeout(function(){
// console.log('2s');
// },2000)
// setTimeout(function(){
// console.log('0秒执行');
// },0)
// // 回调函数队列
// console.log('代码结束执行');


// 读取文件的操作就是异步api,回调
// const fs =require('fs')
// fs.readFile('./demo/2.js','utf8',(err,result) =>{
// console.log(result);
// fs.readFile('./demo/1.js','utf8',(err,result)=>{
// console.log(result);
// })
// })
// console.log('文件读取结果');


// promise 方法 解决node.js异步编程中回调地狱的问题,参数resolve reject,分别表示传递函数,成功和失败,promise有then方法和catch方法
// const fs =require('fs')
// let promise =new Promise((resolve,reject)=>{
// fs.readFile('./demo/1.js','utf8',(err,result) => {
// if(err != null){
// reject(err)
// }else{
// resolve(result)
// }
// })
// })

// promise.then(result=>{
// console.log(result);
// })
// .catch(err=>{
// console.log(err);
// })

const fs = require('fs')
function p1(){
return new Promise((resolve,reject)=>{
fs.readFile('./demo/1.js','utf8',(err,result)=>{
resolve(result)
})
})
}
function p2(){
return new Promise((resolve,reject)=>{
fs.readFile('./demo/2.js','utf8',(err,result)=>{
resolve(result)
})
})
}
function p3(){
return new Promise((resolve,reject)=>{
fs.readFile('./demo/3.js','utf8',(err,result)=>{
resolve(result)
})
})
}

p1().then(r1=>{
console.log(r1);
return p2();
}).then(r2=>{
console.log(r2);
return p3()
}).then(r3=>{
console.log(r3);
})

异步函数

  1. 基于promise函数进行封装
  2. async() 异步函数
  3. await 只能在异步函数中使用
  4. 全局对象 global

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
const fs =require('fs')
const a = require('util').promisify
// 返回文件结果不返回promise对象,无法加async
// 对方法进行处理
const readfile= a(fs.readFile)
// print(readfile)

run();
async function run(){
console.log(await readfile('./1.js','utf8'));
console.log(await readfile('./2.js','utf8'));
console.log(await readfile('./3.js','utf8'))
};

global

1
2
3
4
5
global.console.log('我是')

global.setTimeout(function(){
console.log(123);
},2000)

服务器基础

  1. 端口 区分服务器中提供的不同服务
  2. 数据库 Mongo DB, MySQL

数据库

  1. database 数据库,mongDB数据库软件中可以加你多个数据库
  2. collection 集合 数组
  3. document 文档 json对象
  4. field 字段 json对象属性

mongodb

  1. net stop mongodb 关闭服务
  2. net start mongodb 开启服务
  3. connect 方法链接数据库
  4. 无需创建数据库,mongoDB会根据代码自动判断,创建数据库
  5. 创建集合 对集合设定规则,创建集合 Schema 构造函数

增加文档

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
const mongoose = require('mongoose')

mongoose.connect('mongodb://localhost/playground',{ useUnifiedTopology: true })
.then(()=> console.log('数据库链接成功'))
.catch((err)=>console.log('数据库连接失败'+err))

// 创建集合,Schema 构造函数 model 创建集合 couseSchema

// 创建集合规则
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean,
})

// 使用规则创建集合
const Course = mongoose.model('Course',courseSchema)

// 创建文档 创建集合实例 调用实例对象下的save方法将数据保存到数据库中
// 第一种方法 使用构造函数的方法
// 实例化,与上面的集合规则一致
// const course = new Course({
// name: 'node.js基础',
// author: '欧克',
// isPublished: true
// })
// // save方法保存数据
// course.save()

// 第二种方法,create 向集合中插入文档
Course.create({
name: 'JavaScript',
author: 'world',
isPublished: false
},(err,doc) =>{
console.log(err); // 返回错误信息,null表示插入成功
console.log(doc);
})

// 回调函数,说明也是异步API,通过promise对象的方法接受返回数据
Course.create({
name: 'JavaScript',
author: 'world',
isPublished: false
}).then(result=>{console.log(result)}).catch(err=>console.log(err))

导入数据

  1. mongoimport -d 数据库的名称 -c集合名称 –file 要导入的数据文件·
  2. 如果json文件中包含数组 则使用命令 –jsonArray

查询文档

  1. find()可以查询用户集合下的所有文档
  2. findOne() 默认返回集合中的第一个文档

查看答案

1
2
3
4
5
6
7
8
9
10
11

// 使用规则创建集合
const Course = mongoose.model('Course',courseSchema)

// 查询方法 find 返回一组文档
Course.find({_id:'60531fab2044b239489d9bd6'}).then(result=>console.log(`我返回的是find方法${result}`))


// findOne 方法返回的查询的一个文档,默认返回第一条文档
Course.findOne({_id:'60531fab2044b239489d9bd6'}).then(result=>console.log(`我返回的是findOne方法${result}`))

  1. 使用判断条件查询数据 $gt 和$lt 分别表示><

    查看答案

    \

    1
    Course.find({age: {$gt: 20, $lt: 40}}).then(result=>console.log(`我返回的是指定条件下的集合文档${result}`)).catch(err=>console.log(err))
  2. 查询包含 $in

    查看答案

    1
    Course.find({age:{$in:[21]}}).then(result=>console.log(`我是$in包含条件所返回的集合数据${result}`))
  3. 使用select方法查询数据,如果想要查询某个数据将属性写入select中不想查询某个数据将属性也写入到select中但是要加-

查看答案

1
Course.find().select('name age -_id').then(result=>console.log(`我是select方法下返回的数据${result}`))
  1. 可以根据某个字段对集合数据进行数据的升序和降序的操作,降序操作只需要在在某个属性的前面加个-

查看答案

1
2
3
Course.find().sort('age').then(result=>console.log(`我是经过升序排列后的集合数据${result}`))
Course.find().sort('-age').then(result=>console.log(`我是经过降序排列后的集合数据${result}`))

  1. skip 跳过n个数据,limit限制查询数量

查看答案

1
Course.find().skip(2).limit(3).then(result=>console.log(`我是限制查询下返回的集合数据${result}`))

删除文档

  1. findOneAndDelete 表示删除单个文档
  2. 如果删除的条件匹配个多个文档,默认删除第一个文档
  3. 删除多个文档 deleteMany({}),默认删除全部的文档

查看答案

1
Course.findOneAndDelete({_id:'60532205db7e8e5148e30b56'}).then(result=>console.log(`我是findOneAndDelete方法下返回的集合数据${result}`))

更新文档

  1. updateOne({查询条件},{更改的值}) 更新一个文档
  2. updateMany 更新多个文档

monfoose验证

查看答案

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
const mongoose = require("mongoose");

// 导入数据 使用json文件,导入json文件使用第三方工具 mongoimport -d 数据库的名称 -c数据集合 --file 要导入的数据文件
mongoose.connect('mongodb://localhost/playground', { useUnifiedTopology: true })
.then(() => console.log('数据库链接成功'))
.catch((err) => console.log('数据库连接失败' + err))


// 对创建的规则进行验证处理
const postSchema = new mongoose.Schema({
// 可以将以下的属性值写为 数组的形式 required: [true,‘自定义内容]
title: {
type: String,
// 必传字段
required: true,
// 针对字符
minlength: 2,
maxlength: 5,
// 去除字符串两边的空格
trim: true
},
age: {
type: Number,
min: 18,
max: 100
},
publishDate: {
type: Date,
// default 表示的是默认的值
default: Date.now //返回当前的时间
},
category: {
type: String,
// 枚举 列举出当前字段可以拥有的值
enum: {
values:['html', 'css', 'javascript'],
message:'category的错误信息'
}
},
auchor: {
type:String,
validata:{
// 自定义验证器
validator: v =>{
// console.log();
return v && v.length > 4
},
// 自定义错误的信息
message: '传入的信息不符合规则'
}
}
})

const Post = mongoose.model('Post', postSchema)

// 删除某个数据 使用方法 findOneDelete
// Post.findOneAndDelete({_id:'60544f7106b1d12d0c951070'}).then(result=>console.log('删除成功'))

Post.create({ title: ' aa ', age: 18, category: 'htm' ,auchor: 'bd'})
.then(result => console.log(result))
.catch(error=>{
// 获取错误信息
const err = error.errors
// 循环错误信息
for (var attr in err){
console.log(err[attr]['message']);
}
})

集合关联

  1. 集合关联用到的方法 为 populate(‘关联的对象属性’)
  2. 设置关联的属性类型为 mongoose.Schema.Types.ObjectId, 并将ref的属性值设置为要关联的集合名称

查看答案

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
27
28
29
30
31
32
// 引入需求的库
const mongoose = require('mongoose')
// 连接服务器
mongoose.connect('mongodb://localhost/playground', { useUnifiedTopology: true })
.then(result => console.log(`数据库连接成功${result}`))
.catch(err => console.log(`数据库连接失败${err}`))
// 创建模板并且设置集合规则
const User = mongoose.model('User', new mongoose.Schema({
name: {
type: String
}
}))
// 文章集合规则
const Post = mongoose.model('Post', new mongoose.Schema({
title: {
type: String
},
// 将文章的集合和作者的集合进行关联
auchor: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
}))

// User.create({name:'itmax'}).then(result=>console.log(result))

// Post.create({title:123,auchor:'60545d55a18f3852f853c4e2'}).then(result=>console.log(result))

// 查询数据

Post.find().populate('auchor').then(result=>console.log(result))

用户信息的增删改查案例

  1. 动态生成列表页
  2. 使用mongoDB
  3. 实现对页面数据的增删改查等等

查看答案

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364

const http = require('http')
// 创建服务器
const app = http.createServer()
const url = require('url')
const mongoose = require('mongoose')
// 将表单提交的数据转化,使用querystring.parse方法
const querystring = require('querystring')

// 连接服务器 27017 是默认端口
mongoose.connect('mongodb://localhost/playground', { useUnifiedTopology: true, useNewUrlParser: true })
.then(() => console.log('成功'))
.catch(() => console.log('失败'))
// 创建用户的集合规则
const UserSchema = new mongoose.Schema({
name: {
type: String,
resquired: true,
minlength: 2,
maxlength: 20
},
age: {
type: Number,
min: 3,
max: 80
},
password: String,
email: String,
hobbies: [String]
})
// 创建集合
const user = mongoose.model('User', UserSchema)
// 添加请求事件
app.on('request', async (req, res) => {
// 请求方式
const method = req.method
// 获取请求的地址,使用query属性,将获取到的字符串转换为对象的形式,parse方法后面加true
const { pathname, query} = url.parse(req.url,true)
if (method == 'GET') {
// 呈现页面的方式,增删改
if (pathname == '/list' || pathname == '/') {
// 查询用户的信息
let Users = await user.find()
// console.log(Users);
let list = `<!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>
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@v0.47/js/jquery-3.5.1.min.js"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/js/bootstrap.min.js"></script>
<style>
*{
padding: 0;
margin: 0;
}
.addd{
display:inline-block;
margin: 20px auto;
}
a{
margin:10px
}
.table {
margin: 10px auto;
width: 70%;
}
td span{
margin: 0 5px;
}
</style>
</head>
<body>
<a class="btn btn-success addd" href="/add">添加用户</a>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>用户名</th>
<th>年龄</th>
<th>爱好</th>
<th>邮箱</th>
<th>操作</th>
</tr>
</thead>
<tbody>`
// 对数据进行循环操作
Users.forEach(item => {
list += `<tr>
<td>${item.name}</td>
<td>${item.age}</td><td>`
item.hobbies.forEach(item => {
list += `<span>${item}</span>`
})
list += `</td><td>${item.email}</td><td><a class="btn btn-primary" href="/modify?id=${item._id}">修改</a><a class="btn btn-danger" href="/remove?id=${item._id}">删除</a></td>
</tr>`
})
list += ` </tbody>
</table>
<script>
// css的修改 获取元素
window.addEventListener('DOMContentLoaded',function(){
// 构造函数
let resize = function(){
var adduser = document.querySelector('.addd')
var tablebox = document.querySelector('table')
// console.log(tablebox.offsetLeft);
adduser.style.marginLeft = tablebox.offsetLeft + 'px'
}
// 当页面加载后执行一次,并且窗口改变时跟随变化
resize();
window.addEventListener('resize', () => { var adduser = document.querySelector('.addd')
resize()
}, false);
})
</script>
</body>
</html>`
res.end(list)
}else if(pathname == '/add'){
let add = `<!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>
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@v0.47/js/jquery-3.5.1.min.js"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/js/bootstrap.min.js"></script>
</head>
<style>
* {
padding: 0;
margin: 0;
}

body {
background-color: #ccc;
}

.box {
width: 770px;
margin: 30px auto 0;
border: 2px solid #888;
border-radius: 10px;
}

h5,button{
margin: 20px auto;
text-align: center;
font-size: 20px;
font-weight: 600;
}
.btn{
display: block;
margin-bottom: 10px;
}

.form-control {
width: 93%;
margin: auto;
}

label {
margin-left: 30px;
margin-right: 7px;
}
.hobb{
display: block;
}
</style>

<body>
<div class="box">
<h5>添加用户</h5>
<form method="POST" action="/add">
<div class="form-group">
<label for="username">User Name</label>
<input name="name" type="text" class="form-control" id="username" placeholder="请填写用户名">
</div>
<div class="form-group">
<label for="mima">Password</label>
<input name="password" type="password" class="form-control" id="mima" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputFile">Age</label>
<input name="age" type="number" id="exampleInputFile" placeholder="请输入年龄" class="form-control">
</div>
<div class="form-group">
<label for="exampleInputemail">Age</label>
<input name="email" type="email" id="exampleInputemail" placeholder="请输入邮箱" class="form-control">
</div>

<div class="form-group">
<label for="" class="hobb">hobbies</label>
<label for="football"> 足球</label><input type="checkbox" id="football" name="hobbies" value="足球">
<label for="baseball"> 篮球</label><input type="checkbox" id="baseball" name="hobbies"value="篮球">
<label for="code"> 敲代码</label><input type="checkbox" id="code" name="hobbies"value="敲代码">
<label for="book"> 看书</label><input type="checkbox" id="book" name="hobbies"value="看书">
</div>
<button type="submit" class="btn btn-primary">Add User</button>
</form>
</div>

</body>

</html>`
res.end(add)
}else if(pathname == '/modify'){
// 修改用户信息,获取数据库的中的数据将数据传入页面,使用find返回的是一组对象,使用findOne返回一组对象数据,异步返回
let userid = await user.findOne({_id:query.id})
let hobbiess = ['足球','篮球','羽毛球','学习','看书','敲代码']
console.log(userid);
let modify = `<!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>
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@v0.47/js/jquery-3.5.1.min.js"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/js/bootstrap.min.js"></script>
</head>
<style>
* {
padding: 0;
margin: 0;
}

body {
background-color: #ccc;
}

.box {
width: 770px;
margin: 30px auto 0;
border: 2px solid #888;
border-radius: 10px;
}

h5,button{
margin: 20px auto;
text-align: center;
font-size: 20px;
font-weight: 600;
}
.btn{
display: block;
margin-bottom: 10px;
}

.form-control {
width: 93%;
margin: auto;
}

label {
margin-left: 30px;
margin-right: 7px;
}
.hobb{
display: block;
}
</style>

<body>
<div class="box">
<h5>修改用户信息</h5>
<form method="POST" action="/modify?id=${userid._id}">
<div class="form-group">
<label for="username">User Name</label>
<input value="${userid.name}" name="name" type="text" class="form-control" id="username" placeholder="请填写用户名">
</div>
<div class="form-group">
<label for="mima">Password</label>
<input value="${userid.password}" name="password" type="password" class="form-control" id="mima" placeholder="Password">
</div>
<div class="form-group">
<label for="exampleInputFile">Age</label>
<input value="${userid.age}" name="age" type="number" id="exampleInputFile" placeholder="请输入年龄" class="form-control">
</div>
<div class="form-group">
<label for="exampleInputemail">Age</label>
<input value="${userid.email}" name="email" type="email" id="exampleInputemail" placeholder="请输入邮箱" class="form-control">
</div>

<div class="form-group">
<label for="" class="hobb">hobbies</label>`
// 遍历定义的爱好数组,使用数组中的includes方法来判断数据是否存在
hobbiess.forEach(item=>{
let Hobbies = userid.hobbies.includes(item)
if(Hobbies){
modify += `
<label for="football">${item}</label><input type="checkbox" id="football" name="hobbies" value="${item}" checked>`
}else{
modify += `
<label for="football">${item}</label><input type="checkbox" id="football" name="hobbies" value="${item}">`
}
})
modify += `
</div>
<button type="submit" class="btn btn-primary">Add User</button>
</form>
</div>
</body>
</html>`
res.end(modify)
}else if(pathname == '/remove'){
// res.end(query.id)
await user.findOneAndDelete({_id:query.id})
res.writeHead(301,{
location:'/list'
})
res.end()
}
}
else if (method == "POST") {
// 用户的添加功能
let formData = ''
if(pathname == '/add'){ //接受用户的信息
req.on('data',param=>{
formData += param
})
req.on('end',async () =>{
// 返回表单信息,并将表单信息进行转化
let users = querystring.parse(formData)
// 将解析的信息传入到数据库中
await user.create(users)
// 传入信息后将页面进行重定向,使用写入响应头的方法,301表示重定向
res.writeHead(301,{
location:'/list'
});
res.end()
})
}else if(pathname == '/modify'){
req.on('data',param=>{
formData += param
})
req.on('end',async () =>{
// 返回表单信息,并将表单信息进行转化
let users = querystring.parse(formData)
// 将解析的信息修改传入到数据库中 updataOne方法中第一个参数表示查询条件,第二修改的数据对象
await user.updateOne({_id:query.id},users)
// 传入信息后将页面进行重定向,使用写入响应头的方法,301表示重定向
res.writeHead(301,{
location:'/list'
});
res.end()
})
}
}
// res.end('ok')
})
// 设置监听
app.listen(3100)

模板引擎

  1. art-template 模板引擎
  2. 模板语法
  3. 标准语法 原始语法

查看答案

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
4. `{{}}` 标准语法,原始语法`<%=数据 %>`
### 原文输出
1. `{{@ }}` 标准语法
2. `<%- 数据%>` 原始语法
### 条件判断
1. 标准语法 `{{if 条件}} 。{{else if }}。{{else}}。{{ /if }} `
2. 原始语法 ` <% if(value) { %>...<% } else if (value) {%> 内容 <%} else{%> content <%}%>`
### 循环
1. 标准语法` {{each 数据 }{{$index}}{{$value}} {{/each}} `
2. 原始语法 `<% for() {%><%} %>`
### 子模版
1. 标准语法 `{{include '模板'}}`
2. 原始语法`<%include('模板')%>`
### 模板继承
1. 将网站的html骨架抽离到独立的文件中,其他页面模板可以继承骨架文件
2. `{{entend '继承的模板'}}`
3. 使用`{{block ‘名称}}{{/block}}`
​```js
const template = require('art-template')
const path = require('path')
// template方法是用来拼接字符串,join方法将位置拼接
const views = path.join(__dirname,'view','index.html')

const html = template(views,{
name: 'ad',
age:18,
content:'<h3>我是标题</h3>',
users:[{
name:'a',
age:19,
sex:'男'
},{
name:'b',
age:20,
sex:'男'
},
{
name:'c',
age:25,
sex:'女'
},
]
})
console.log(html);
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
{{block 'head'}}{{/block}}
<!-- 标准语法引入子模版 -->
{{include './header.art'}}
<!-- 标准语法 -->
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ 1 + 2 }}</p>
<p>{{ 1*0 == 0 }}</p>
<!-- 原文输出 -->
<p>{{@ content }}</p>
<p>{{ content }}</p>
<!-- 条件判断 -->
<span>{{if age > 10}} 年龄大于10 {{/if}}</span>
<!-- 循环 -->
<ul>
{{ each users }}
<li>{{ $value.name }}</li>
<li>{{ $value.age }}<span>{{if age > 10}} 年龄大于10 {{/if}}</span></li>
<li>{{ $value.sex }}</li>
{{/each}}
</ul>
<!-- 原始语法 -->
<p>
<%= name %>
</p>
<p>
<%= content %>
</p>
<!-- 原文输出 -->
<p>
<%- content %>
</p>
<!-- 条件判断 -->
<span>
<%if(age>10){%>年龄大于10<%}%>
</span>
<!-- 循环 -->
<ul>
<%for(var i=0;i < users.length;i++){ %>
<li>
<%= users[i].name%>
</li>
<li>
<%= users[i].age%>
</li>
<li>
<%= users[i].sex%>
</li>
<% }%>
</ul>
<!-- 原始语法引入子模版 -->
<%include ('./footer.art')%>
<!-- 加入模块继承使用标准语法中的block双标签填充 -->

*/

模板配置

  1. template.defaults.imports.变量名 = 变量值
  2. 生成项目文件 npm init -y
  3. 使用第三方模块router 实现路由
  4. 对静态资源处理 serve-static
  5. 处理日期的第三方模块 dateformat

查看答案

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
27
28
29
30
31
32
33
34
35
36
37
38
const http = require('http')
// 导入连接数据库的模块
require('./model/connect')
// 有变量传入因此需要使用model.exports将变量引入
const Student = require('./model/user')
// 创建网站服务器
const app = http.createServer();
// 引入router模块
const getRouter = require('router')
// 获取路由对象
const router = getRouter();
// 引入模板引擎
const template = require('art-template')
// 引入path模块
const path = require('path')
// 配置模块的根目录
template.defaults.root = path.join(__dirname,'views')
// template.defaults.extname = '.art'
// 引入静态资源访问模块
const serveStatic = require('serve-static');
// 实现静态资源访问服务
const serve = serveStatic(path.join(__dirname,'public'))
// 呈递学生档案信息页面
router.get('/add',(req,res)=>{
let html = template('add.art',{})
res.end(html)
})
// 呈递列表页面
router.get('/list',(req,res)=>{
res.end('list')
})
app.on('request',(req,res)=>{
// 页面启用路由功能
router(req,res,()=>{})
// 页面启用静态资源访问功能
serve(req,res,()=>{})
})
app.listen(80)

route路由代码

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

// 有变量传入因此需要使用model.exports将变量引入
const Student = require('../model/user')
// 引入模板引擎
const template = require('art-template')
// 引入querystring模块
const querystring = require('querystring')
// 引入router模块
const getRouter = require('router')
// 获取路由对象
const router = getRouter();
// 呈递学生档案信息页面
router.get('/add',(req,res)=>{
let html = template('add.art',{})
res.end(html)
})
// 呈递列表页面
router.get('/list',async (req,res)=>{
// 查询学生信息
let students = await Student.find()
console.log(students);
let html = template('list.art',{
students: students
})
res.end(html)
})
// 实现学生信息添加功能路由
router.post('/add',(req,res)=>{
let formData = '';
req.on('data',param =>{
formData += param
})
req.on('end',async ()=>{
await Student.create(querystring.parse(formData));
// 重定向第二个参数为对象
res.writeHead(301,{
location:'/list'
})
res.end()
})

})
// 将router方法暴露出来给其他模块使用
module.exports = router

模块代码

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
27
28
29
30
const http = require('http')
// 导入连接数据库的模块
require('./model/connect')
// 创建网站服务器
const app = http.createServer();
// 引入模板引擎
const template = require('art-template')
// 引入path模块
// 将router方法从模块中导入使用require方法
const router = require('./route/index')
const path = require('path')
// 引入处理日期的第三方模块 dateFormat
const dateformat = require('dateformat')
// 配置日期的模块处理,模块中的第一个参数表示自定义的属性名,第二个参数表示要显示的日期格式
template.defaults.imports.dateformat = dateformat
// 配置模块的根目录
template.defaults.root = path.join(__dirname,'views')
// template.defaults.extname = '.art'
// 引入静态资源访问模块
const serveStatic = require('serve-static');
// 实现静态资源访问服务
const serve = serveStatic(path.join(__dirname,'public'))

app.on('request',(req,res)=>{
// 页面启用路由功能
router(req,res,()=>{})
// 页面启用静态资源访问功能
serve(req,res,()=>{})
})
app.listen(80)