node=day4

本节知识点

  

注意:这里是基于文件,而不是数据库;CRUD为增删改查
crud是指在做计算处理时的增加(Create)、读取(Retrieve)、更新(Update)和删除(Delete)

 

大纲

  

  

  

 

 

 

 

 

 

   

 

(1)复习

  

   

   

   

 

 

   

(2)文件操作路径'/'与模块标识路径'/'

  1、文件操作路径

    

   2、模块标识路径

    

     

     

注意:这里.js后缀可以直接省略

    

这里可以直接传参调用

    

     

   3、分析先后顺序

    

结果为先输出模块读取结果,后输出文件读取结果,原因分析如下
  所有文件操作的API都是异步的,类似于ajax请求

   4、路径以/开头

    

文件操作下以/开头,表示磁盘根路径

  5、小结

    

     

     

注意:
    文件操作路径可以省略./,读取同级文件
    模块操作路径不可省略./

    文件操作路径和模块操作路径如果以/开头,则都是读取磁盘根路径

 

     

(3)Express-helloworld案例

  1、新建项目目录express-demo

  2、使用指令创建package.json项目说明文件

npm init [--yes]

  3、参照package.json中的main选项,新建入口执行文件index.js

  4、下载安装第三方模块npm i express --save(模块后面不加版本默认下载当前最新版)

    

   5、开始编写index.js入口文件脚本

启动服务器,监听端口

    

添加响应处理,设置请求处理函数

    

     

原生的API依旧可以使用

    

对比:
    express可以直接使用res.send()方法返回响应,且无需处理请求头Contype-Type类型
    原生语法需要针对不同响应内容,对应处理其请求头Contype-Type类型

 

  6、并行路径处理

相对于原生的if...else if...else判断处理路径,这里可以直接并行处理,更加简洁直观

    

 

 

(4)nodemon工具自动重启服务

目前为止编写完代码后都需要重启一次服务才可以使用,接下来利用第三方模块nodemon工具即可自动重启服务

  

注意:
    在任意目录执行安装该模块命令都可以,也就是说,说有需要 --global来安装的包都可以在任意目录位置执行命令进行安装

  检测是否安装成功

nodemon --version或者nodemon -v,如下所示

  

   接下来通过nodemon启动服务

node index.js替换为nodemon index.js

  

   至此,以后便不用再频繁重启服务器来查看效果

以后每次Ctrl+S保存代码,便会自动重启一次

  

 

 

   

 

 

 

(5)Express中static-server静态资源服务

  

   1、开放某些公共静态资源

正常情况下,无法和Apache服务器一样,直接通过路径访问资源

    

接下来配置静态资源目录

   

   

 

  2、相关

    

  3、其他写法

    ①省略第一个参数,简化路径操作

      

      

 

 

     ②别名设置

      

这里重命名为static,此时便可以使用/static/来替代/public/

      

      同理,也可以设置其他别名

      

  4、小结

一般开发推荐设置别名为静态文件目录名
如果不加别名设置则可以直接在url后加上文件名访问

  

 

 

  

 

(6)基本路由

 

路由介绍

  

 

   

   作用:实现资源分发处理

  

   开发一般会编写到路由映射表

  

 

(7)Express中使用模板引擎art-template

  

  

  接下来将之前的反馈系统重做一遍,利用Express框架

  1、将之前的public和views文件拿到该项目目录下

    

  2、开放静态资源

    

           

  3、Express中配置使用art-template

    

    

   4、配置(查看官方文档):

    

    

  5、 使用模板引擎渲染

    

     接下来测试下

    

    这里第二个参数为可宣传参数,如果没有模板替换数据,则可以不写

     接下来看下效果

    

此时发现无法预览,原因:后缀默认必须为art才可以

    

之所以改后缀名为art,更好辨识该模板要被template渲染。但这样会造成编辑器IDE无法高亮识别代码
另外,如果不想修改为art,可以修改配置

    

     

  6、如果为嵌套于子目录的模板,则按照目录结构依次读取

    

 

     

 

       

  7、传递替换数据

    

       

    

   8、视图渲染存储目录

    修改views默认模板存储目录

Express有个默认约定:开发人员将视图模板放置到views目录下,如果想修改可以通过如下API

    

 

            

  9、配置使用小结

    

 

(8)Express留言板案例

  1、代码

var express = require('express')
var app = express()
/*开放静态资源*/
app.use('/public/',express.static('./public/'))

/*配置使用art-template模板引擎*/
app.engine('html',require('express-art-template'))
/*修改默认(视图渲染存储目录)模板文件存放目录
    加入将views目录放到public下的views,则可以修改如下
*/
app.set('views','./public/views')
/*路由*/
var comments = [
    {name:'tony',message:'你好tony,感觉人生达到了巅峰',dateTime:'2016-02-12'},
    {name:'bob',message:'你好bob,感觉人生达到了巅峰',dateTime:'2016-03-02'},
    {name:'jack',message:'你好jack,感觉人生达到了巅峰',dateTime:'2016-11-18'}
]
app.get('/',function(req,res){
    res.render('index.html',{
        comments:comments
    })
})
app.get('/post',function(req,res){
    res.render('post.html')
})
app.get('/pinglun',function(req,res){
    var comment = req.query
    comment.dateTime = '2017-11-11'
    comments.unshift(comment)
    /*Express重定向API*/
    res.redirect('/')
    /*
        res.statusCode = 302
        res.setHeader('Location','/')
        res.end()结束响应
    */
})
app.listen(3000,function(){
    console.log('app is running at port 3000...')
})

  这里注意:“使用Express框架后,不再需要设置状态码302,然后通过响应头重定向”,这里借用重定向API---res.redirect()

  

 

 

 

 

(9)Express中post请求

  表单提交数据时最好使用post请求,所以接下来使用post请求测试下

  1、前言

因为原生node实现post请求较为繁琐,一般开发时不自行编写post。
这里使用express框架封装好的post请求去进行交互

 

  2、post方式处理表单请求

     ①首先将表单提交方式改为post

      

    ②编写post响应,测试数据

由下面可以分析出可以利用不同的请求方法(post、get),让一个请求路径(/pinglun)可以使用多次

      

 

 

      此时提交表单数据时,服务器便会做出对应处理,如下所示

      

    ③响应处理步骤

      

    ④获取post请求头数据

req.query方式只能获取get方式请求数据

      因为post方式请求数据会将数据放到请求头里

      

    ⑤获取post请求数据

      

Express没有封装解析表单post请求体数据的API,所以这里要借助插件--middleWare中间件

      

其中body-parse便是专门用于解析表单post请求体

 

  3、body-parse第三方包使用步骤

    安装后结合文档配置好即可,具体配置步骤不用记忆

    

 

 

     

  4、body-parse第三方包使用

    ①下载

      

    ②配置body-parser中间件

      

    ③测试

      

 

 

       

此时便可以获取post请求体数据,接下来可以做下一步处理

    ④获取并处理数据,重定向

      

    ⑤完整代码

var express = require('express')
var bodyParser = require('body-parser')

var app = express()
/*开放静态资源*/
app.use('/public/',express.static('./public/'))

/*配置使用art-template模板引擎*/
app.engine('html',require('express-art-template'))
/*修改默认(视图渲染存储目录)模板文件存放目录
    加入将views目录放到public下的views,则可以修改如下
*/
app.set('views','./public/views')

/*配置body-parse请求体第三方包*/
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())

/*路由*/
var comments = [
    {name:'tony',message:'你好tony,感觉人生达到了巅峰',dateTime:'2016-02-12'},
    {name:'bob',message:'你好bob,感觉人生达到了巅峰',dateTime:'2016-03-02'},
    {name:'jack',message:'你好jack,感觉人生达到了巅峰',dateTime:'2016-11-18'}
]
app.get('/',function(req,res){
    res.render('index.html',{
        comments:comments
    })
})
app.get('/post',function(req,res){
    res.render('post.html')
})

app.post('/pinglun',function(req,res){
    var comment = req.body
    comment.dateTime = '2017-11-11'
    comments.unshift(comment)
    /*Express重定向API*/
    res.redirect('/')
})
/*这里已经无效,不过可以看出一个路径可以使用多种方法进行操作*/
app.get('/pinglun',function(req,res){
    var comment = req.query
    comment.dateTime = '2017-11-11'
    comments.unshift(comment)
    /*Express重定向API*/
    res.redirect('/')
    /*
        res.statusCode = 302
        res.setHeader('Location','/')
        res.end()结束响应
    */
})
app.listen(3000,function(){
    console.log('app is running at port 3000...')
})

    ⑥小结

      

所以不用加res.end()手动结束

      

  

(10)crud起步

   1、在开始新项目之前首先创建好基础目录

    ①新建项目目录curd-code

    ②创建package.json

    ③创建说明文件中main选项对应的入口执行文件index.js

    ④创建默认视图渲染存储目录views

    ⑤创建静态资源开放目录public

    ⑥下载安装第三方模块

    

  2、读取响应结果,返回index.html页面

     

     结果如下

    

这里发生报错,原因在于没有安装和配置模板引擎

  3、安装配置模板引擎

     

     

 

 

     此时再次验证,结果如下

    

  4、编辑html模板

使用服务端不用太关注样式,所以找个模板直接套过来用
这里去bootstrap官网找个模板过来直接使用

    

 

     然后将模板代码复制到index.js

    

 

     接下来修改模板相关资源

  5、修改模板文件

    ①因为该模板依赖bootstrap,所以下载bootstrap包

       

      

     ②引用bootstrap资源

      因为bootstrap模块下载到了node_modules目录,所以这里需要开放node_modules目录

      

      接下来修改引入资源路径

       

     ③自定义样式表

      这里IE10兼容样式表可以先去掉

      

       自定义样式表dashboard.css,去官网拔取即可,拔取后放到public开放资源目录下

      

       再往下,兼容IE9的代码暂时除去

      

       底部的jQuery暂时不用,也去除

      

       接下来做个循环测试下

      

 

 

       

 

 

       

 

 

       接下来开始制作持久化存储,在介绍数据库前,首先将信息存储到文件

 

(11)文件读取数据(操作文件)

    1、创建

    项目根目录下创建db.json,存放基本数据

一般都有id标识,gender性别0为男,1为女
之所以不让用“男女”去标记存储,是因为0和1占用的控件更小一些

    接下来写入基本存储数据,如下所示

{
    "students":[
        {"id":1,"name":"张三","gender":0,"age":18,"hobby":"游戏"},
        {"id":2,"name":"张四","gender":0,"age":16,"hobby":"代码"},
        {"id":3,"name":"张五","gender":1,"age":18,"hobby":"电影"},
        {"id":4,"name":"张六","gender":1,"age":23,"hobby":"音乐"},
        {"id":5,"name":"张七","gender":0,"age":25,"hobby":"爬山"},
        {"id":6,"name":"张八","gender":1,"age":24,"hobby":"游泳"},
        {"id":7,"name":"张九","gender":0,"age":26,"hobby":"跳舞"},
        {"id":8,"name":"张十","gender":1,"age":22,"hobby":"弹琴"}
    ]
}

    之后将该文件数据渲染至index.html

  2、修改遍历index.html文件

    

     接下来首先在index.js里写个students做个测试

    

     结果如下

    

  3、读取文件数据

注意:Express框架没有提供读取文件相关操作,所以这里需要使用原生fs

    

     验证如下

    

  4、字符解析

    接下来解析字符即可

    

注意:文件读取信息出来是字符串,需要再次转化即JSON.parse(data)才可以

 

(12)小结

  

 

 

(13)crud路由设计

针对项目简单写个设计文档

  

  1、路由模块提取

项目根目录下新建路由配置文件router.js

    然后将路由配置相关内容放置router.js

    

 

     而index.js入口文件作用只是:启动服务器、配置相关信息

    

  2、非正式方法

    先来个简单测试,这里将index.js中的模块导出,然后在路由文件引入,接着启动路由文件。因为路由文件里导入了index.js,所以仍然可以正常启动

    

 

     

接下来启动服务器

    

 

     测试后可以正常访问。

但此时入口文件已经不再是index.js而是router.js,这种非正式方式不推荐使用    

  3、合理提取

    

 

     

    导出方法后,在入口文件引入调用,这种方法较之前来说较为合理,但也不方便,Express提供了一种更好方式

  4、Express包装路由

Express包装路由步骤
    1、创建路由容器router
    2、将路由挂载至router容器
    3、导出容器router

    

接下来将express框架创建的路由容器router挂载到app服务实例中

    

 

此时入口文件作用如下

    

路由文件作用如下
  处理路由;根据不同的请求方法+请求路径,设置具体的请求函数

    注意:

模块职责要清晰,不可混用
划分模块的目的就是为了增强代码的可维护性,提升开发效率

 

(14)处理添加页面+配置body-parse中间件

  首先修改下路由文件配置,结合路由设置文档,如下

     

  1、新建new.html文件写入内容,这里直接去bootstrap官网引用表单

    

 

     接下来设置路由信息,查看效果

    

 

     

  2、修改链接,点击跳页

    

  3、完善学生信息表单

    

注意:
      表单name值必填项

        

  4、接下来开始服务配置

1、获取表单数据
2、处理
3、发送响应

    因为是post请求,而express里没有获取post请求的API,结合之前步骤,开始安装配置

    

 

 

      

注意:配置模板引擎和body-parse中间件,一定要在挂载路由实例之前(中间件的执行流程,由上至下)

  5、获取表单数据

    上面配置完post请求数据中间件后,开始进行测试。利用req.body获取。

这里可能会有小问题

    

 

 

     这里只需要将body-parse中间件解析配置中的false改为true即可

    验证如下:

    

 

 

       点击提交后,服务器接收打印信息

这里注意表单的name作用:name 属性用于对提交到服务器后的表单数据进行标识
注意:只有设置了 name 属性的表单元素才能在提交表单时传递它们的值。
简单来说,name就是提交到后台的索引,比如在复选框中都要设置成name="hobby"说明几个复选框都在爱好下。

      此时,服务器接收到输入信息

      

  6、获取表单数据后,开始数据处理,保存至db.json用以持久化

做法:
    首先读取文件信息--字符串,转换为对象,然后添加新增学生信息,最后再转为字符串存到json文件
即字符串→对象→字符串

 

(15)封装提取student数据操作模块

  新建student.js文件封装增删改查的相关API,只处理数据,不关心业务(处理表单数据...等业务)

  

  1、获取所有学生列表

这里需要用到fs核心模块

    

 

 

     但有个问题,fs文件操作模块为异步操作,这里需要结合回调函数去获取文件数据

    

 

 

     修改如下

    

    接下来注释find

    

     接下来做下测试,修改之前路由映射文件中读取文件操作

    

此后,如果再有其他地方需要用到student学生数据,只需要加载student模块,调用student.find()自定义API即可
里面只关心数据,没有业务逻辑

 

(16)封装异步API

  详见下节文章

 

(17)封装保存学生的API

  最终调用形式如下

  

   1、分析

同理,与之前类似,保存学生信息前需要先读取文件,所以可以将之前读取操作直接copy过来,再加以修改

  

  2、保存数据

    

 

 

     接下来还需要添加学生id

这里注意:id可以理解为学生的身份证,必须具有唯一性;且就算后期被删除,新添加的人也不可能继承之前删除(去世)人的身份证号码,这里先进行简单处理

    

添加id方法,找到最后一个id,然后加1即可

    

  3、保存的API已经完成,接下来开始调用API,实现存储

     

 

    完整如下

 

     

此时便实现了数据的持久化存储,因为此时的数据已经存储到了json文件

    

以上便是异步编程,node核心

 

(18)回调函数

获取异步数据

  

 

(19)编辑学生页面

根据ID来更新

  

  1、首先第一步,又需要读取文件

    

 

     遍历查找对应数据

    

ES6语法:find查找遍历

    

  2、查找到具体数据后,开始修改

    常用的简单修改,一次重新赋值,如下所示

    

 

     但这种过于累赘,直接使用for..in循环(遍历拷贝对象)即可

    

  3、接下来将新对象转为字符串,再进行存储

    

  4、接下来调用API进行测试

    

在路由配置文件,进行测试。
此时访问localhost:3000/students/edit便可以成功修改更新数据

    

 

     

  5、编写更新页面(静态部分)

    与之前新增页面类似,所以这里直接复制过来加以修改,然后设置路由配置

    

     测试如下

    

  6、添加编辑按钮,进行跳转

    

 

        

     此时鼠标悬停时左下角便可以对应显示

     

  7、接下来开始进行渲染

    首先需要获取点击的id

    

 

 

     接下来使用模板引擎进行定向渲染,因为需要根据id获取学生信息,所以接下啦再来封装一个API用来查找单个学生

  8、查找单个学生API

    

 

 

     做下测试调用

    

 

 

     然后点击某个需要编辑的学生,查看服务器输出内容,此时发现可以正常获取所选信息

    

 

 

     最后进行渲染

    

 

 

     接下来编辑静态模板部分

    

 

 

     

注意:这里需要用到art-template的条件语句,查看文档如下

    

 

 

     同理,修改下首页的性别显示,按照0男1女的格式设置

    

 

 

     结果如下

    

     

(20)更新功能

  

   1、点击提交按钮时,完成提交

    表单的action和method已经写出,接下来设置路由即可

    

 

 

     接下来添加id标识

注意:这里便用到了type=hidden,即不希望被客户看到,但需要被提交到服务器的内容

    

    提交测试下,可以正确获取新内容

    

     

 

  2、第一步获取已经完成,接下来调用API进行更新

    

 

 

     接下来修改个人信息后,点击提交测试下,发现报错

    

 

 

     分析:传过来的id为字符串,所以需要进行转换,或者直接将===改为==,不判断类型(之前也有多出需要修改);或者依次手动转换

    

 

(21)删除功能

  

  1、首先获取要删除的id

    

 

 

     

 

 

     此时点击删除便可以在控制台获取对应id

    

  2、根据id进行删除操作,所以接下来封装删除API,API只负责数据操作,不管业务逻辑

    

 

     然后进行调用,编写对应业务逻辑

同理传入回调函数,回调函数参数为error
如果失败则存在error,如果成功则error为null

        

  3、编写删除API

    首先删除对应元素

    

 

     删完后,将students重写进去

    

 

     接下来做下测试,调用API

    

 

     完整代码如下

    

 

     

 

     至此便可以实现删除功能

接下来可以添加确认框,提高用户体验,防止误操作

    如下所示:

    

 

 

(22)总结

  

 

   

 

   

 

   

 

   

模块化思想:模块思想要单一

 

 

  

 

.

posted @ 2020-01-06 10:04  剑仙6  阅读(143)  评论(0编辑  收藏  举报
欢迎访问个人网站www.qingchun.在线