天天看点

实战Node:幼教平台幼教资源部分实现

实现幼教平台的幼教资源部分功能,主要熟悉Node中前后端交互以及和数据库进行交互

​​幼教平台完整项目代码​​

这个项目陆陆续续看了有两三遍,终于完整的整理完了,Node的项目主要还是做后端服务器的提供接口的,前端界面还是主要用Vue、react来做,Vue可以参考​​实战Vue:基于Vue的移动端购物商城​​

前端界面展示

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

项目目录结构

实战Node:幼教平台幼教资源部分实现

(一)项目初始化(不借助express-genertor)

新建文档school

实战Node:幼教平台幼教资源部分实现

在school文档下新建app.js入口文件

实战Node:幼教平台幼教资源部分实现

进行npm初始化

实战Node:幼教平台幼教资源部分实现

使用express搭建服务器

① 安装express ​

​npm install express --save​

​ ② 启动服务器

实战Node:幼教平台幼教资源部分实现

③ 匹配基础路径

实战Node:幼教平台幼教资源部分实现

④ 完成设置

实战Node:幼教平台幼教资源部分实现

配置babel,实现高阶语法转化

① 配置转化环境:根目录新建​

​.babelrc​

​,并在里面添加如下代码

实战Node:幼教平台幼教资源部分实现

安装并设置为开发依赖​

​npm install babel-preset-env --save-dev​

实战Node:幼教平台幼教资源部分实现

② 安装babel-register转化工具​

​npm i babel-register --save-dev​

实战Node:幼教平台幼教资源部分实现

设置不再使用app.js向外暴露,新建src文件夹,将app.js放在src目录下。新建main.js。

实战Node:幼教平台幼教资源部分实现

main.js中,首先引入语法转换工具,然后引入app.js。就可以将app.js中的高阶语法转换为低阶语法。

babel高阶语法转化演示

① 安装

​npm install -g babel-cli​

​ 全局安装

​npm install babel-cli --save-dev​

​ 项目中安装

② 通过​

​babel 文件名​

​进行演示

实战Node:幼教平台幼教资源部分实现

③ 通过​

​babel src -d dist​

​将src中文件转换为低阶语法版本

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

设置package.json中,实现开发和生产分离

实战Node:幼教平台幼教资源部分实现

设置完成后,就可以使用​

​npm run dev​

​命令进行项目运行,并且可以使用es6语法了,同时使用​

​npm run build​

​命令进行打包将高阶语法转化为低阶语法,使用​

​npm run start​

​命令运行低阶语法版本

(二)项目分析

幼教平台是一个全栈项目,应该分为三部分

实战Node:幼教平台幼教资源部分实现

在实际开发过程中,一般先打通后端接口,前端只需要进行请求即可。

前端主要做幼教资源部分,一通百通,其他界面都类似:

实战Node:幼教平台幼教资源部分实现

后台管理系统

实战Node:幼教平台幼教资源部分实现

(三)项目开发

1. 配置依赖资源

新建public、views文件夹,引入静态资源

① 新建public文件夹,存放公共资源

实战Node:幼教平台幼教资源部分实现

② 新建views文件夹,存放所有界面

实战Node:幼教平台幼教资源部分实现

③ 因为要区分前后端,所以public和views中,各自新建back、web文件夹

实战Node:幼教平台幼教资源部分实现

集成静态资源文件

将静态界面以及资源内容放到对应文件夹中

实战Node:幼教平台幼教资源部分实现

配置全局路径

① src目录下新建config.js,并在里面设置路径代码

实战Node:幼教平台幼教资源部分实现

② 在app.js中引入并配置全局资源

实战Node:幼教平台幼教资源部分实现

配置新的模板引擎(使用Nunjucks)

① 安装Nunjucks​

​npm install nunjucks --save​

实战Node:幼教平台幼教资源部分实现

② 在app.js中进行配置

实战Node:幼教平台幼教资源部分实现

配置全局路由

① 新建routes文件夹,存放各种路由

实战Node:幼教平台幼教资源部分实现

② routes文件夹下,新建index.js。该文件用于配置首页路由

实战Node:幼教平台幼教资源部分实现

③ 配置index.js。因为最后在语法转换的时候,src文件夹下的文件进行转换,所以在index.js中,使用common.js或者es6语法均可。

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

④ 在app.js中,引入路由并进行路由挂载

实战Node:幼教平台幼教资源部分实现

⑤ 此时就可以通过​​

​​

​​访问后端界面

实战Node:幼教平台幼教资源部分实现

⑥ 同理,可以在index.js中配置前端路由

实战Node:幼教平台幼教资源部分实现

配置nodemon:自动重启项目工程

① 安装​

​npm install -g nodemon​

实战Node:幼教平台幼教资源部分实现

② 更改package.json中的开发命令

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

服务器启动后

实战Node:幼教平台幼教资源部分实现

此时更改代码后,就可以自动更新了

2. 路由重定向

服务器接收命令后,使用​

​res.redirect(url)​

​进行路由重定向

实战Node:幼教平台幼教资源部分实现

在这里,将​

​'/'’​

​重定向为​

​'/web'​

​,也就是访问​​

​​

​​后,会直接重定向到​​

​​

​​

3. 配置公共代码模板

后端界面可以将头部以及侧边栏进行抽离,别的界面在使用的时候,直接使用Nunjucks进行集成就可以

实战Node:幼教平台幼教资源部分实现

设置完基础模板后,在index.html中进行继承即可

实战Node:幼教平台幼教资源部分实现

4. 配置简单的404界面

  1. 书写简单404界面
    实战Node:幼教平台幼教资源部分实现
  2. 在app.js所有中间件最后配置404错误界面
    实战Node:幼教平台幼教资源部分实现
  3. 此时访问没有的资源就会出现错误提示
    实战Node:幼教平台幼教资源部分实现

5. 配置前台界面

  1. 配置幼教资源以及具体文章路由
    实战Node:幼教平台幼教资源部分实现
  2. 在界面上,将a标签跳转链接,改为路由的形式
    实战Node:幼教平台幼教资源部分实现

6. 幼教资源中轮播图的实现

在routes中,新建sowing.js,用来配置轮播图接口路由,并配置基础路由代码

实战Node:幼教平台幼教资源部分实现

路由设计

① 图示:实现以下界面数据动态化

实战Node:幼教平台幼教资源部分实现

② 新增一张轮播图

ⅰ请求方法:POST

ⅱ请求路径:/sowing/add

ⅲ 请求参数

  1. image_url 图片路径
  2. image_link 跳转链接
  3. image_title 图片标题
  4. s_time 上架时间
  5. e_time 下架时间
  6. l_edit 最后编辑
  7. c_time 添加时间

③ 获取所有轮播图

ⅰ请求方法:GET

ⅱ请求路径:/sowing/api/list

④ 通过ID获取一条轮播图

ⅰ请求方法:GET

ⅱ请求路径:/sowing/api/singer/:sowingId

ⅲ 注意:通过url拼接的方法,获取轮播图ID

⑤ 根据ID修改轮播图

ⅰ请求方法:POST

ⅱ请求路径:/sowing/api/edit

ⅲ 请求参数

  1. ID 轮播图ID
  2. image_url 新图片路径
  3. image_link 新跳转链接
  4. image_title 新图片标题
  5. s_time 新上架时间
  6. e_time 新下架时间
  7. l_edit 新最后编辑
  8. c_time 新添加时间

⑥ 根据ID删除轮播图

ⅰ请求方法:GET

ⅱ请求路径:/sowing/api/remove/:sowingId

ⅲ 注意:通过url拼接获取轮播图ID

后台管理轮播图实现

可以直接使用req.body获取数据的原因是配置了POST请求中间件。

① 新增一张轮播图

配置接口API

实战Node:幼教平台幼教资源部分实现

配置添加轮播图页面路由

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

② 获取所有轮播图

配置接口API

实战Node:幼教平台幼教资源部分实现

加载轮播图列表路由配置

这里采用的是服务器端渲染的方法,所以首先查询了所有的数据,并将数据作为参数传递给sowing_list界面,并在界面中调用模板语法进行渲染

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

③ 通过ID获取一张轮播图/font>

  1. 配置接口API
    实战Node:幼教平台幼教资源部分实现

④ 根据ID修改轮播图

配置接口API

实战Node:幼教平台幼教资源部分实现

修改轮播图路由配置

实战Node:幼教平台幼教资源部分实现

在轮播图列表中,点击删除按钮后,可以通过两种方式在编辑界面获取数据:① 直接将所有数据从列表界面获取,传递到编辑界面。② 向编辑界面传递一个图片id,编辑界面通过id调用接口,获取一张轮播图的数据。这里采用第二种方式。

实战Node:幼教平台幼教资源部分实现

在轮播图编辑界面中,首先需要通过路径截取id,获取一张轮播图数据,并注入界面。

实战Node:幼教平台幼教资源部分实现

图片缩略图的地方,需要监听文件变化,当文件变化的时候,监听事件并读取文件,当文件读取完毕,将缩略图路径赋值为新的图片路径

实战Node:幼教平台幼教资源部分实现

当用户修改完数据提交后,发起新的提交表单请求

实战Node:幼教平台幼教资源部分实现

⑤ 根据ID删除轮播图

  1. 配置接口API
    实战Node:幼教平台幼教资源部分实现
  2. 修改删除路由配置
    实战Node:幼教平台幼教资源部分实现

前端展示界面实现

① 后端在返回路由的时候,直接将所有的轮播图数据查询出来,并且返回

实战Node:幼教平台幼教资源部分实现

② 前端直接使用模板语法进行渲染即可

实战Node:幼教平台幼教资源部分实现

7. 用户中心版块

用户模型

实战Node:幼教平台幼教资源部分实现

接口处理

① 添加管理员接口,在后面/user会被屏蔽,不会进行用户名密码的判断

实战Node:幼教平台幼教资源部分实现

② 用户和密码登录接口

在验证用户存在后,如果密码匹配成功,会将user._id用户的id信息存储在req.session.token中,即在session中存储客户端的信息。同时,再返回的结果中,将用户ID存储在token中,方便前端存储在localStorage中

实战Node:幼教平台幼教资源部分实现

在前端界面,也将md5加密后的用户名密码传递到服务器进行处理

实战Node:幼教平台幼教资源部分实现

③ 退出登录

实战Node:幼教平台幼教资源部分实现

④ 获取用户信息——部分

实战Node:幼教平台幼教资源部分实现

用户信息修改

实战Node:幼教平台幼教资源部分实现

⑤ 获取用户信息——全部

实战Node:幼教平台幼教资源部分实现

前端个人中心界面展示

实战Node:幼教平台幼教资源部分实现

⑥ 根据ID(token)修改一条数据信息

实战Node:幼教平台幼教资源部分实现

⑦ 根据ID(token)修改密码

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

路由配置

实战Node:幼教平台幼教资源部分实现

权限控制

在服务器端,使用session存储用户数据,并将session保存到MongoDB数据库。同时,使用中间件进行判断。

​​Node.js:使用session存储用户信息​​ ① 在middle_wares文件夹下,新建login_pass.js文件,同时设置中间件

实战Node:幼教平台幼教资源部分实现

② 在app.js中,进行引入并挂载中间件

实战Node:幼教平台幼教资源部分实现

③ 在所有的轮播图接口前面,加上/back

实战Node:幼教平台幼教资源部分实现

④ 这样在访问后端接口或页面的时候,就必须先登录才能访问了。

8. 后端幼教资源管理

用户模型

实战Node:幼教平台幼教资源部分实现

接口处理

① 图片上传到upload文件夹

实战Node:幼教平台幼教资源部分实现

② 向数据库中插入一条新记录

实战Node:幼教平台幼教资源部分实现

③ 根据ID修改文章

实战Node:幼教平台幼教资源部分实现

④ 根据ID删除文章

实战Node:幼教平台幼教资源部分实现

路由配置

实战Node:幼教平台幼教资源部分实现

9. 前端幼教资源展示

  1. 接口设置

    ① 获取总页数

    实战Node:幼教平台幼教资源部分实现
    ② 获取列表页数据
    实战Node:幼教平台幼教资源部分实现
    ③ 前台获取资源列表
    实战Node:幼教平台幼教资源部分实现
    ④ 前台获取详情页数据
    实战Node:幼教平台幼教资源部分实现
    ⑤ 前端详情页页面阅读量处理
    实战Node:幼教平台幼教资源部分实现
  2. 界面动态请求接口加载数据渲染界面
    实战Node:幼教平台幼教资源部分实现

10. 使用Mongoose与MongoDB交互,存储数据

使用​

​npm i mongoose --save​

​安装mongoose

实战Node:幼教平台幼教资源部分实现

建模:Schema(模式对象),Schema对象定义约束了数据库中的文档结构

① 在根目录下,新建models文件夹,存放所有模型

实战Node:幼教平台幼教资源部分实现

② 在models下新建Sowing.js,规定轮播图模式,模式的作用就是mongoose在与数据库进行交互,进行增删改查的时候,进行借鉴使用的

实战Node:幼教平台幼教资源部分实现

③ 在Sowing.js中,进行导入mongoose并连接数据库,并监听连接成功或失败

实战Node:幼教平台幼教资源部分实现

④ 创建模式Schema,并创建一个Model向外暴露。Mongoose 的一切始于 Schema。每个 schema 都会映射到一个 MongoDB collection ,并定义这个collection里的文档的构成。

实战Node:幼教平台幼教资源部分实现

在sowing.js轮播图路由中,引入Sowing模式,并进行相关操作,配置接口。

11. Node中POST请求

​​Node.js:POST请求、文件上传​​

12. Node中,使用中间件处理POST请求

在根目录下新建middle_wares文件夹存储中间件。

实战Node:幼教平台幼教资源部分实现

过滤get请求

实战Node:幼教平台幼教资源部分实现

如果是普通表单(application/x-www-form-urlencoded)提交,要处理,以拼接的形式;如果有文件(图片、音视频····multipart/form-data),不要处理

实战Node:幼教平台幼教资源部分实现

其他情况,需要进行处理。

① 数据流拼接

② 使用querystring解析和格式化字符串。

实战Node:幼教平台幼教资源部分实现

完整的POST中间件

import querystring from 'querystring'
// 处理post请求
export default (req, res, next) => {
// 1. 过滤get请求
if (req.method.toLowerCase() === 'get') {
return next();
    }
// 2. 如果是普通表单提交,要处理,以拼接的形式
// application/x-www-form-urlencoded
// 如果有文件(图片、音视频····),不要处理,multipart/form-data
if (req.headers['content-type'].startsWith("multipart/form-data")) {
return next();
    }

// 3. 数据流的拼接
let data = "";
req.on("data", (chunk) => {
data += chunk;
    });
req.on("end", () => {
req.body = querystring.parse(data);
next();
    })
}      

挂载中间件,在app.js中引入body_parse,并且在所有路由前进配置数据处理中间件

实战Node:幼教平台幼教资源部分实现

13. Node中,使用中间件处理error

  1. 需求:出现错误的时候,通过中间件,将错误存储到数据库中
  2. 在models中,新建Error.js,新建错误模型
    实战Node:幼教平台幼教资源部分实现
  3. 在middle_wares文件夹中,新建error_log.js,作为错误中间件处理错误。
    实战Node:幼教平台幼教资源部分实现
  4. 在app.js中引入并挂载错误中间件
    实战Node:幼教平台幼教资源部分实现

14. 路由跳转

与Vue直接在页面中通过router跳转不同的是,Node项目中,使用html的a标签跳转,直接将路径放在a标签的href属性内即可。

实战Node:幼教平台幼教资源部分实现

15. 模板的渲染

在之前的基础学习中,是使用ejs进行渲染的。在这个项目中,使用的是Nunjucks进行渲染。这两种服务器端渲染方法都大同小异。

​​Nunjucks文档## 标题​​

​​EJS文档​​

16. 在src目录下,有一个config.js配置文件。

在这个文件夹下,定义了一些路径,定义好后,在app.js中引入,就可以在别的文件中使用了。

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

17. 模糊路径匹配

在路径中,使用​

​路径/:name​

​,冒号后面的就是模糊匹配

在服务器接口中,使用​

​req.params.name​

​获取值

实战Node:幼教平台幼教资源部分实现

18. 图片、文件等资源的上传,使用formidable

​​Node.js:借助formidable文件上传​​

19. 集成文本编辑器 ​​wangEditor​​

20. 分页

有刷新

给上一页下一页按钮绑定路由仍然为source_list

实战Node:幼教平台幼教资源部分实现

在点击后,页面相当于进行刷新,此时,后端接口会接收两个参数, 页数和每一页显示的数量,根据公式查询结果,并渲染界面返回前端

实战Node:幼教平台幼教资源部分实现

无刷新:集成分页插件:​

​twbs-pagination​

​​​twbs-pagination文档​​ 配置获取总页数接口以及获取列表页面数据的接口,供分页插件使用

实战Node:幼教平台幼教资源部分实现
实战Node:幼教平台幼教资源部分实现

21. 项目的重构

后端

async/await

① 概念

  1. 现在最常用的异步变成方案
  2. async函数时Generator函数的语法糖
  3. 具备特点

    ① 内置执行器

    Generator函数的执行必须依靠执行器,而async函数自带执行器,调用方式和普通函数的调用一样

    ② 更好的语义

    async和await相较于*和yield更加语义化

    ③ 更广的适用性

    co模块约定,yield命令后面只能是Thunk函数或Promise对象

    而async函数的await命令后面则可以是Promise或者原始类型的值(Number、string、boolean,但这时等同于同步操作)

    ④ 返回值是promise

    async函数返回值是Promise对象,比Generator函数返回的Iterator对象方便,可以直接使用then()方法进行调用

② 使用

  1. async是“异步”的简写,async function用于声明一个function是异步的;await,可以认为是async wait的简写,用于等待一个异步方法执行完成
  2. async/await是一个用同步思维解决异步问题的方案(等结果出来之后,代码才会继续执行)
  3. 可以通过多层async function的同步写法代替传统的callback嵌套

在项目中如果要是用async/await,需要安装和配置​

​transform-runtime​

​ ① 步骤:​

​npm i babel-plugin-transform-runtime -D​

​ ② 配置​

​.babelrc​

实战Node:幼教平台幼教资源部分实现

③ 不安装则会报错​

​regeneratorRuntime is not defined​

​错误

MVC设计模式

将项目转换为MVC模式,首先要将业务逻辑从router中抽离出来,下面以sowing.js为例

① 新建controller文件夹,并在controller文件夹下新建sowing文件夹,并在sowing文件夹下新建SowingController.js

实战Node:幼教平台幼教资源部分实现

② 将sowing.js中的业务逻辑,全部放到SowingController.js中

在sowing.js中

实战Node:幼教平台幼教资源部分实现

而在SowingController.js中

实战Node:幼教平台幼教资源部分实现

此时,只需要在sowing.js中引入SowingController.js,并且在接口处使用SowingController中的方法即可。

实战Node:幼教平台幼教资源部分实现

所有的接口转移完成后

sowing.js中

实战Node:幼教平台幼教资源部分实现

SowingController.js中

实战Node:幼教平台幼教资源部分实现

端口号配置

各个环境下,nodejs可以通过process.env.PORT去设置端口号

比如

① linux环境下

​PORT=1234 node app.js​

​ 使用上面命令每次都需要重新设置,如果想设置一次永久生效,使用下面命令

​export PORT=1234​

​​

​node app.js​

​ ② windows环境下

​set PORT=1234​

​​

​node app.js​

​ package.json配置文件

实操

在package.json中设置

实战Node:幼教平台幼教资源部分实现

在config.js中设置

实战Node:幼教平台幼教资源部分实现

在app.js中监听

实战Node:幼教平台幼教资源部分实现

中间件session抽取——config.js

实操:

在config.js中设置常量

实战Node:幼教平台幼教资源部分实现

在app.js中直接使用config.js中的数据进行配置即可

实战Node:幼教平台幼教资源部分实现

集成插件chalk

① 简介:chalk是一个颜色的插件,可以通过比如:​

​chalk.blue("hello world")​

​之类的方法来改变颜色

② 使用

  1. 下载:​

    ​npm install chalk​

  2. 引入:​

    ​import chalk from 'chalk'​

  3. 显示:​

    ​console.log(chalk.blue("Hello world!"));​

封装数据库连接

① 简介:全局连接数据库

② 实现:

  1. 在根目录下新建文件夹db,在bd文件夹下新建db.js,db.js中实现连接数据库
'use strict';
import mongoose from 'mongoose';
import config from './../src/config';
mongoose.connect(config.db_url, {useNewUrlParser: true});
mongoose.Promise = global.Promise;
const db = mongoose.connection;

db.once('open' ,()=>{
console.log('连接数据库成功~~~~~~');
});

db.on('error', (error)=>{
console.error('连接数据库时发生错误: ' + error);
mongoose.disconnect();
});

db.on('close', function() {
console.log('数据库断开,重新连接数据库');
mongoose.connect(config.db_url, {useNewUrlParser: true});
});

export default db;      

在app.js中引入

实战Node:幼教平台幼教资源部分实现

前端