Node.js-Express框架

  • Express 是一个基于 Node.js 平台,快速、开放、极简的 web 开发框架 ,用来快速搭建Web服务。
  • Express 是一个第三方模块,有丰富的 API 支持,强大而灵活的中间件特性。
  • Express 不对 Node.js已有的特性进行二次抽象,只是在它之上扩展了 Web 应用所需的基本功能
  • 本质是使用各种中间件,快速的搭建服务。 

1.安装

  • 使用 npm init 命令为应用程序创建 package.json 文件。

npm init -y(如果文件夹的名字是中文可以直接输入‘npm init’,手动输入name)

做项目时可以直接复制 package.json 文件然后npm install,按照package.json里记录的内容进行安装。

  • 安装install

 npm install express

注意:

  • 项目目录名字不要取中文,也不要取express ,package.json 文件里的name也不要取express

  • 如果安装不成功

    • 换个网络环境

    • 运行下npm cache clean -f,再重装试试

2.使用

注意: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() 。

3.express下的art-template:

  • 安装

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】

4.托管静态资源

让用户直接访问静态资源是一个web服务器最基本的功能。

  • 静态资源:不是动态进行更改的。

图片:http://localhost:3000/1.png
CSS样式:http://localhost:3000/css/style.css
静态JS:http://localhost:3000/js/index.js

 4.1限制前缀

通过限制前缀的方式来决定web服务上的路径是否开放,把可以随便访问的静态文件放在开放的路径下,而需要受保护的文件放在不开放的路径下,想通过前端的请求请求不到,只有服务器响应给对方的情况下才能拿到。

// 限制访问前缀(前端的请求) static静态(托管的是服务端的一个文件夹路径)
app.use('/public', express.static('public'))

这意味着想要访问public下的内容,必须要在请求url中加上/public 

4.2post接口 

利用post请求获取数据的时候需要利用中间件

4.3中间件 

当使用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是键值对的形式,可以拿到前端请求的数据 。

4.4利用Express框架搭建留言板

引入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框架下本身就存在路由中间件。

4.5路由

路由是指确定应用程序如何处理客户端的请求。路由(Routing)是由一个 URL(或者叫路径标识)和一个特定的 HTTP 方法(GET、POST 等)组成的,涉及到应用如何处理响应客户端请求。每一个路由都可以有一个或者多个处理器函数,当匹配到路由时,这些个函数将被执行。

  • 捕获请求,根据预先配置,分析请求,把相应的请求给到相应的组件

路由的中间件

步骤:

  1. 利用nodejs的模块化,分模块定义路由中间件(创建一个router.js文件),并导出
  2. 在入口文件中,导入并使用路由中间件

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');
})

5.Express示例 

Bootstrap中文网 (bootcss.com)

学生列表:

  1. 显示学生相关信息(name ; gender ; age ; hobbies)
  2. 并添加一个ADD按钮,提供添加学生功能
  3. “删除”提供删除其所在行的功能;“编辑”对所在行信息进行编辑。    

Node.js-Express框架_第1张图片

package.json

Node.js-Express框架_第2张图片 

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

6.利用MongoDB写学生列表

之前的是单独读取数据文件,现在用mogoose的API去访问数据库

Node.js-Express框架_第3张图片

 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

你可能感兴趣的:(node.js,前端,开发语言,npm)