Node.js-项目(一)

图书管理系统

项目:https://github.com/dreamsgarden/node_books

采用 MVC 架构,基于 node.js 的 koa + art-template + mysql, bootstrap布局,实现图书的增删改查。

在这里插入图片描述


一、项目架构


1.SSR 服务端渲染

将组件或页面通过服务器生成html字符串,再把渲染的完整的页面发送到浏览器

2.CSR 客户端渲染

通过接口请求数据,前端通过JS动态处理和生成页面需要的结构和页面展示

二、项目搭建

1.初始化项目

npm init -y
books/
|
+- config <-- 配置文件
|
+- controllers <-- 控制层
|
+- middlewares <-- 错误中间件
|
+- models <-- 模型层
|
+- publics <-- 静态资源
|
+- views <-- 视图层
|
+- app.js <-- 入口文件
|
+- package.json <-- 项目描述文件
|
+- node_modules/ <-- npm安装的所有依赖包

2.入口文件

npm install koa

app.js

const Koa = require('koa')
const app = new Koa()

app.use(ctx => {
  ctx.body = 'Hello Koa';
});

app.listen(config.port, () => {
  console.log('server is running...')
})

3.注册路由

使用 koa-simple-router 路由

安装

npm install koa-simple-router

用法

const Koa = require('koa')
const router = require('koa-simple-router')

const app = new Koa()

app.use(router(_ => {
    _.get('/', (ctx, next) => {})

    _.post('/name/:id', (ctx, next) => {})
}))

controllersroute.js 处理路由

const router = require('koa-simple-router')

const Controller = require('./index')

const controller = new Controller()

module.exports = (app) => {
  app.use(
    router((_) => {
      _.get('/', controller.index())
      
      // 首页
      _.get('/index', controller.index())
    })
  )
}

controllers 下 index.js 处理业务逻辑

class IndexController {
  constructor() {}
  // 首页
  index() {
    return (ctx, next) => {
      ctx.body = 'Hello Koa'
    }
  }
}

module.exports = IndexController

app.js 中 开启路由

// 开启路由
require('./controllers/route')(app)

4.模板配置

使用 art-template 模板引擎

安装

npm install --save art-template koa-art-template

app.js

const render = require('koa-art-template')

// 配置 koa-art-template
render(app, {
  root: path.join(__dirname, 'views'), // 视图的位置
  extname: '.html', // 后缀名
  debug: process.env.NODE_ENV !== 'production', //  是否开启调试模式
})

app.use(async function (ctx) {
  await ctx.render('user')
})

views中创建 layout.htmlindex.html,使用模板继承


5.静态资源

npm install koa-static

app.js

// 静态文件
app.use(static(path.join(__dirname, 'public')))

6.错误处理

middlewares 下 index.js

const middlewares = {
  error(app) {
    app.use(async (ctx, next) => {
      try {
        await next()
      } catch (err) {
        console.log(err)
        ctx.status = 500
        ctx.body = '服务器忙,请稍后重试!'
      }
    })
    app.use(async (ctx, next) => {
      await next()
      if (ctx.status != 404) return

      ctx.status = 404
      ctx.body = `<script type="text/javascript" src="//qzonestyle.gtimg.cn/qzone/hybrid/app/404/search_children.js" charset="utf-8"></script>`
    })
  },
}
module.exports = middlewares

6.配置

config 下 index.js

let config = {
  port: 3000,
  mysql: {
    host: 'localhost', // 主机地址
    user: 'root1', // 用户名
    password: '123456', // 密码
    database: 'test', // 数据库名
    
  }
}

module.exports = config

三、设计路由

请求方式请求路径GET/POST参数说明
GET/index获取图书
GET/addpage添加图书页
POST/add添加数据处理
GET/editpage修改图书页
POST/edit修改数据处理
GET/delete删除图书

四、数据模型

1.使用 MySQL数据库,设计表结构,创建模型文件

2.调用模型,获取数据 并 传递给视图

npm init mysql

封装 mysql

const config = require('../config')

module.exports.query = (sql, data = null) => {
  return new Promise((resolve, reject) => {
    const mysql = require('mysql')

    const connection = mysql.createConnection(config.mysql)

    connection.connect()

    connection.query(sql, data, (error, results) => {
      if (error) return reject(error)

      resolve(results)
    })

    connection.end()
  })
}

图书数据模型(增删改查)

const db = require('./db')

/**
 * 图书数据模型(增删改查)
 * @type {[type]}
 */
class BookModel {
  constructor() {}

  /**
   * 获取图书列表
   * @return {[type]}
   */
  async find() {
    let meta = {
      code: 0,
      message: '',
      data: [],
    }

    try {
      let data = await db.query(`SELECT * FROM book`)
      // console.log(data)

      if (data.length > 0) {
        meta.data = data
        meta.message = '获取成功'
        return Promise.resolve(meta)
      } else {
        meta.code = 1
        meta.message = '获取失败'
        return Promise.reject(meta)
      }
    } catch (err) {
      // console.log(err)
      meta.code = 1
      meta.message = err.message
      return Promise.reject(meta)
    }
  }
  
  /**
   * 根据 id 获取图书信息
   * @param  {Number}   id       图书 id
   * @return {[type]}
   */
   
  async findById(id) {}
  /**
   * 添加图书
   * @param  {Object}   book      图书对象
   * @return {[type]}
   */
  async add(book) {}
	
  /**
   * 更新图书
   * @param  {[type]}   book      图书对象
   * @return {[type]}
   */
  async update(book) {}

  /**
   * 删除图书
   * @param  {[type]}   id       图书 id
   * @return {[type]}
   */
  async deleteById(id) {}
}

module.exports = BookModel

五、SSR 服务端渲染

  1. contreollersroute.js 处理路由
const router = require('koa-simple-router')

const Controller = require('./index')

const controller = new Controller()

module.exports = (app) => {
  app.use(
    router((_) => {
      _.get('/', controller.index())
      
      // 获取图书
      _.get('/index', controller.index())

      // 添加图书
      _.get('/addpage',controller.addpage())
      _.post('/add',controller.add())

      // 修改图书
      _.get('/editpage',controller.editpage())
      _.post('/edit',controller.edit())

      // 删除图书
      _.get('/delete',controller.delete())
    })
  )
}
  1. contreollersindex.js 处理业务,调用数据模型,获取数据传递给视图
const BookModel = require('../models')

const bookModel = new BookModel()

class IndexController {
  constructor() {}

  // 获取图书
  index() {
    return async function (ctx) {
      try {
        let res = await bookModel.find()
        // console.log(res)

        if (res.code == 0) {
          ctx.render('index', {
            data: res.data,
          })
        } else {
          ctx.body = '获取失败'
        }
      } catch (err) {
        console.log(err)
      }
    }
  }
  // 添加图书页
  addpage(){}
  
  // 添加数据处理
  add() {}
  
  // 修改图书页
  editpage(){}
  
  // 修改数据处理
  edit() {}
  
  // 删除图书
  delete() {}
}

六、CSR 客户端渲染

1.后台输出接口

修改 contreollersindex.js ,返回 JSON 数据

const BookModel = require('../models')

const bookModel = new BookModel()

class IndexController {
  constructor() {}

  // 获取图书
  index() {
    return async function (ctx) {
      try {
        let res = await bookModel.find()
        // console.log(res)

        ctx.body = res

        // if (res.code == 0) {
        //   ctx.render('index', {
        //     data: res.data,
        //   })
        // } else {
        //   ctx.body = '获取失败'
        // }
      } catch (err) {
        console.log(err)
      }
    }
  }
}

2. 前端 Ajax 调用

public 下新建 index.htmlbootstrap布局,Ajax请求数据,art-template渲染数据,

toastr.js是一个基于jQuery的非阻塞、简单、漂亮的消息提示插件,使用简单、方便。


七、RESTful API

一套关于设计请求的规范。

  • GET: 获取数据
  • POST: 添加数据
  • PUT: 更新数据
  • DELETE: 删除数据

1.设计路由

请求方式请求路径GET/POST参数说明
GET/book获取图书
POST/book添加图书
GET/book/:id根据 id 获取图书
PUT/book修改图书
DELETE/book:id删除图书

2.修改路由

contreollersroute.js

module.exports = (app) => {
  app.use(
    router((_) => {
      _.get('/', controller.index())

      // 获取图书
      _.get('/book', controller.index())

      // 添加图书
      _.post('/book', controller.add())

      // 根据 id 获取图书
      _.get('/book/:id', controller.editpage())

      // 修改图书
      _.put('/book', controller.edit())

      // 删除图书
      _.delete('/book/:id', controller.delete())
  )
}

3.获取动态路由参数

contreollersindex.js

修改图书页 和 删除图书 获取 id

let id = ctx.params.id

4. 调用接口


总结

这是 学习 Node.js 的初次项目,总结一下开发

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值