npm init
命令为应用程序创建 package.json
文件。npm init -y(如果文件夹的名字是中文可以直接输入‘npm init’,手动输入name)
做项目时可以直接复制 package.json
文件然后npm install,按照package.json
里记录的内容进行安装。
npm install express
注意:
项目目录名字不要取中文,也不要取express ,package.json
文件里的name也不要取express
如果安装不成功
换个网络环境
运行下npm cache clean -f
,再重装试试
注意:http模块下响应结束的标志是res.end(),而express框架下响应结束的标志是res.send()。
// 0. 加载 Express
const express = require('express')
// 1. 调用 express() 得到一个 app
// 类似于 http.createServer()
const app = express()
// 2. 设置请求对应的处理函数
// 当客户端以 GET 方法请求 / 的时候就会调用第二个参数:请求处理函数
//相当于sever.on监听get方法
app.get('/', (req, res) => {
res.send('hello world')
})
// 3. 监听端口号,启动 Web 服务
app.listen(3000,()=>{
console.log('running');
})
app.get('/')相当于添加个事件监听:当用户以get方式求"/"时,它后面的回调函数会执行,其回调函数中的req,res与前面所学http模块保持一致。
res.send()是exprss提供的方法,不是nodejs提供的 ,用于结束本次请求。类似的还有res.json(),res.sendFile() 。
npm i express-art-template
前提是需要先引入express框架。
app.engine('html', require('express-art-template'))//把express-art-template相应内容引入到express框架下,应用于html类文件。
引入express-art-template就可以使用render的方式渲染页面了,但是在express框架下不需要用对象去接收【var str=tempalte.render('',{});res,end(str)】,而是直接集成在response上,直接【res.render】
让用户直接访问静态资源是一个web服务器最基本的功能。
图片:http://localhost:3000/1.png
CSS样式:http://localhost:3000/css/style.css
静态JS:http://localhost:3000/js/index.js
通过限制前缀的方式来决定web服务上的路径是否开放,把可以随便访问的静态文件放在开放的路径下,而需要受保护的文件放在不开放的路径下,想通过前端的请求请求不到,只有服务器响应给对方的情况下才能拿到。
// 限制访问前缀(前端的请求) static静态(托管的是服务端的一个文件夹路径)
app.use('/public', express.static('public'))
这意味着想要访问public下的内容,必须要在请求url中加上/public
利用post请求获取数据的时候需要利用中间件
当使用post请求,需要利用中间件获取post请求提交的数据,中间件是一个特殊的url地址处理函数。
body-parser
安装:
npm i body-parser
引入:
var bodyParser=require('body-parser')
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
ps:使用中间件后req上会有一个body属性,req.body是键值对的形式,可以拿到前端请求的数据 。
引入express,express-art-template,body-parser
var express = require('express')
var app = express()
//利用post接口需要引入中间件
var bodyParser=require('body-parser')
var arr = [
{
name: 'aa',
content: 'bbb',
timer: '2018-11-2 17:11:22'
},
{
name: 'bbb',
content: 'cccc',
timer: '2028-11-2 17:11:22'
}
]
//静态托管 限制前缀(限制的是请求端的)
app.use('/public', express.static('./public'))//只要是放在public文件夹下的就可以访问
//http://127.0.0.1:2000/public/bootstrap.css
//引入art-template
app.engine('html', require('express-art-template'))//把express-art-template相应内容引入到express框架下
//应用于html文件
//中间件的配置
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
//get类型接口 渲染页面
app.get('/', (req, res) => {
res.render('index.html', { list: arr })//利用res.render渲染页面时需要把页面放到views文件夹下,才找的到,不用写路径,直接写文件名就会自动去找。
})
//a标签的请求类型是get
app.get("/post",(req,res)=>{
//跳转页面的时候不需要拿数据直接渲染就ok
res.render('post.html')
})
//post类型接口 渲染页面
app.post("/pinglun",(req,res)=>{
//点击提交按钮的时候需要传数据,利用中间件提交的数据会直接放在req.body里
// console.log(req.body);//{ name: 'sss', content: 'ww' }
var obj=req.body
obj.timer=new Date().toLocaleString()
arr.unshift(obj)
//重定向
res.redirect('/')
})
app.listen(2000, () => {
console.log('run');
})
ps:把所有接口放在一起就可以称之为路由 ,路由接收所有前端的请求,并且判断请求给谁,然后把相应的请求给到相应的组件。在express框架下本身就存在路由中间件。
路由是指确定应用程序如何处理客户端的请求。路由(Routing)是由一个 URL(或者叫路径标识)和一个特定的 HTTP 方法(GET、POST 等)组成的,涉及到应用如何处理响应客户端请求。每一个路由都可以有一个或者多个处理器函数,当匹配到路由时,这些个函数将被执行。
路由的中间件
步骤:
router.js
var express=require('express')
//创建路由对象
var router=express.Router()
var arr = [
{
name: 'aa',
content: 'bbb',
timer: '2018-11-2 17:11:22'
},
{
name: 'bbb',
content: 'cccc',
timer: '2028-11-2 17:11:22'
}
]
router.get('/',function(req,res){
res.render('index.html',{list:arr})
})
router.get('/post',function(req,res){
res.render('post.html')
})
router.post('/pinglun',function(req,res){
var obj=req.body
obj.timer=new Date().toLocaleString()
arr.unshift(obj)
res.redirect('/')
})
//模块化,向主文件引入router.js,exports只能添加属性、方法,rpourt是对象类型,module.exports可以添加对象
module.exports=router
main.js
var express = require('express')
var app = express()
//引入router.js文件
var router=require('./05-router.js')
//利用post接口需要引入中间件
var bodyParser=require('body-parser')
//静态托管 限制前缀(限制的是请求端的)
app.use('/public', express.static('./public'))//只要是放在public文件夹下的就可以访问
//http://127.0.0.1:2000/public/bootstrap.css
//引入art-template
app.engine('html', require('express-art-template'))//把express-art-template相应内容引入到express框架下
//应用于html文件
//中间件的配置
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
//引入路由
app.use(router)
app.listen(2000, () => {
console.log('run');
})
Bootstrap中文网 (bootcss.com)
学生列表:
package.json
main.js主文件
//安装express,art-template,express-art-template,body-parser
//引入,然后进行相关的配置,使用中间件,使用路由,启动配置
var express=require('express')
var app=express()
//引入中间件
var bodyParser=require('body-parser')
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
//引入路由
var router=require('./router.js')
//引入express-art-template
app.engine('html',require('express-art-template'))
//托管静态文件
app.use('/public',express.static('./public'))
app.use('/node_modules',express.static('./node_modules'))
app.use(router)
app.listen(3000,()=>{
console.log('running');
})
router.js 路由
//移入具体操作文件的模块,引入依赖的组件
var express=require('express')
//路由对象
var router=express.Router()
//引入curd.js
var curd=require('./curd.js')
//把文件的增删改查抽取出来放在curd.js中
//显示根目录(信息首页)
router.get('/',function(req,res){
curd.showAll(function(err,data){
if(err){
return res.send('error')
}
res.render('index.html',{
fruit:['香蕉','苹果','西瓜','榴莲'],//四个球
list:data//列表数据
})
})
})
//渲染添加学生信息界面
router.get('/add',function(req,res){
res.render('new.html')
})
//添加学生信息
router.post('/stu/add',function(req,res){
//拿到form表单提交的数据
var obj=req.body
// console.log(obj);//{
// name: 'wwwww',
// gender: '1',
// age: '2',
// hobbies: 'wev'
// }
//把表单提交的数据作为参数传给add方法
curd.add(obj,function(err){
if(err){
res.send('add stu error')
}
res.redirect('/')
})
})
//删除一条学生信息
router.get('/remove',function(req,res){
// console.log(req.query);//{ id: '1' } 因为点的是remove,我们之前在(index.html里的)remove上只之拼接了id
curd.removeById(req.query.id,function(err){
//把要删除的数据的id传给curd,让其处理
if(err){
return res.send('remove filed')
}
//重定向
res.redirect('/')
})
})
//编辑信息 编辑信息跳转edit页面,选择编辑的应该显示在页面上
router.get('/edit',function(req,res){
curd.showById(req.query.id,function(err,data){
if(err){
return res.send('edit err')
}
res.render('edit.html',{
student:data
})
})
})
//编辑后更新一条学生信息
router.post('/stu/edit',function(req,res){
var obj=req.body
curd.update(obj,function(err){
if(err){
return res.send('edit error')
}
res.redirect('/')
})
})
//导出router
module.exports=router
db.json数据
{
"stu":[
{
"name":"a1",
"gender":"man",
"age":"11",
"hobbies":"qqqq",
"id":"1"
},
{
"name":"a2",
"gender":"man",
"age":"12",
"hobbies":"cccc",
"id":"2"
},
{
"name":"a3",
"gender":"woman",
"age":"13",
"hobbies":"eeee",
"id":"3"
}
]
}
curd.js读取文件
//操作相应的内容 在router里调用 读取相应文件
var fs = require('fs')
//展示信息
exports.showAll = function (callback) {
//callback 需要将结果返回到调用showAll的地方去
fs.readFile('./db.json', function (err, data) {
if (err) {
return callback(err)//callback(err,data)里边两个参数
}
// fs.readFile读取文件是buffer类型,需要转换成字符串类型,然后JSON.parse()转换成对象类型
data = JSON.parse(data.toString()).stu//转换成对象类型
callback(null, data)//callback(err,data)里边两个参数
})
}
//添加信息
exports.add = function (stud, callback) {//这里的stud代表前边(router)传过来的参数,用来接收
//拿到提交的数据都是字符串形式(router.js里的log),但是db.json里的age是数值型,需要类型转换成数值型
stud.age = parseInt(stud.age)
fs.readFile('./db.json', function (err, data) {
if (err) {
return callback(err)
}
//拿到db.json里的数据
//fs.readFile读取文件是buffer类型,需要转换成字符串类型,然后JSON.parse()转换成对象类型
data = JSON.parse(data.toString()).stu
//提交的数据没有id这一项,所以我们应该添加一下id
if (data.length == 0) {
stud.id = 1
} else {
stud.id = data[data.length - 1].id + 1
}
//添加数据
data.push(stud);
//将data重新写回数据库中
data = {
"stu": data
}
//需要重新将数据转换成字符串形式
data = JSON.stringify(data)
//将更新过的数据写入db.json里
fs.writeFile('./db.json', data, function (err) {
if (err) {
return callback(err)
}
callback(null)
})
})
}
//删除一条学生信息
exports.removeById = function (id, callback) {
//因为db.json里的id是数值类型,而前边传过来的id是字符串类型
id = parseInt(id)
fs.readFile('./db.json', function (err, data) {
if (err) {
return callback(err)
}
data = JSON.parse(data.toString()).stu//因为后边.stu了,所以拿到的是数组
var ret = data.findIndex(function (item) {//item代表数组中的每一项
return item.id === id
})
data.splice(ret, 1);
//将data重新写回去
data = {
"stu": data
}
data = JSON.stringify(data)
fs.writeFile('./db.json', data, function (err) {
if (err) {
return callback(err)
}
callback(null)
})
})
}
//通过id查找一条学生信息
exports.showById = function (id, callback) {
id = parseInt(id)
fs.readFile('./db.json', function (err, data) {
if (err) {
return callback(err)
}
data = JSON.parse(data.toString()).stu
var ret = data.find(function (item) {//find查找数组中的某一项
return item.id === id
})
callback(null,ret)
})
}
//更新学生信息
exports.update=function(obj,callback){
obj.id=parseInt(obj.id)
obj.age=parseInt(obj.age)
fs.readFile('./db.json',function(err,data){
if(err){
return callback(err)
}
data=JSON.parse(data.toString()).stu
var ret=data.find(function(item){
return item.id===obj.id
})
for(var key in ret){
ret[key]=obj[key]
}
data={
"stu":data
}
data=JSON.stringify(data)
fs.writeFile('./db.json',data,function(err){
if(err){
if(err){
return callback(err)
}
}
callback(null)
})
})
}
edit.html 编辑页面
edit|remove
之前的是单独读取数据文件,现在用mogoose的API去访问数据库
curd-mongodb.js
const mongoose=require('mongoose')
mongoose.connect('mongodb://localhost:/stu')
const Cat=mongoose.model('Cat',{
name:{type:String,required:true}//required:true指的是必须得填这一项
,age:{type:String}
,gender:{type:String,default:0,enum:[0,1]}//default:0设置默认值,enum:[0,1]只能是0,1
,hobbies:{type:String}
})
//所有的方法在建立的模型上
module.exports=Cat//导出数据模型
router.js
//移入具体操作文件的模块,引入依赖的组件
var express=require('express')
//路由对象
var router=express.Router()
//引入curd.js
var curd=require('./curd-mongodb.js')//此时的curd就是curd-mongodb.js里创建的模型
//然后就可以直接调用模型上的API
//显示根目录(信息首页)
router.get('/',function(req,res){
//Model.find()查询所有
curd.find(function(err,data){
if(err){
return res.send('error')
}
res.render('index.html',{
fruit:['香蕉','苹果','西瓜','榴莲'],//四个球
list:data//列表数据
})
})
})
//渲染添加学生信息界面
router.get('/add',function(req,res){
res.render('new.html')
})
//添加学生信息
router.post('/stu/add',function(req,res){
//拿到form表单提交的数据
var obj=req.body
//把数据作为参数传给方法
// new一个实例 这个实例就是提交的数据new curd(obj)
new curd(obj).save(function(err){
if(err){
res.send('add stu error')
}
res.redirect('/')
})
})
//删除一条学生信息
router.get('/remove',function(req,res){
// console.log(req.query);//{ id: '1' } 因为点的是remove,我们之前在(index.html里的)remove上只之拼接了id
curd.findByIdAndRemove(req.query.id,function(err){
if(err){
return res.send('remove filed')
}
//重定向
res.redirect('/')
})
})
//编辑信息 编辑信息跳转edit页面,选择编辑的应该显示在页面上
router.get('/edit',function(req,res){
curd.findById(req.query.id,function(err,data){
if(err){
return res.send('edit err')
}
res.render('edit.html',{
student:data
})
})
})
//编辑后更新一条学生信息
router.post('/stu/edit',function(req,res){
var obj=req.body
curd.findByIdAndUpdate(obj.id,obj,function(err){//更新的时候需要传ID
if(err){
return res.send('edit error')
}
res.redirect('/')
})
})
//导出router
module.exports=router