Node.js学习 (十一)模块化功能

使用前面的案例定义模块化简单案例

一、路由设计
请求方法 请求路径 get 参数 post 参数 备注
GET /studens 渲染首页
GET /students/new 渲染添加学生页面
POST /studens/new name、age、gender、hobbies 处理添加学生请求
GET /students/edit id 渲染编辑页面
POST /studens/edit id、name、age、gender、hobbies 处理编辑请求
GET /students/delete id 处理删除请求
二、路由模块

express.Router() 路由模块,使用express框架更方便一些
处理路由
根据不同的请求方法+请求路径设置具体的请求处理函数、

router.js:

  1. 创建一个路由容器
var fs = require('fs')//读取文件模块
var Student = require('./student')//Student 模块下面定义
var router = express.Router()// 配置路由器
  1. 把路由都挂载到 router 路由容器中

    router.get()
    router.post()

/*
 * 渲染学生列表页面
 */
router.get('/students', function (req, res) {
//Student模块定义的查询
  Student.find(function (err, students) {
    if (err) {
      return res.status(500).send('Server error.')
    }
    res.render('index.html', {
      fruits: [
        '苹果',
        '香蕉',
        '橘子'
      ],
      students: students
    })
  })
})

/*
 * 渲染添加学生页面
 */
router.get('/students/new', function (req, res) {
  //渲染new.html
  res.render('new.html')
})

/*
 * 处理添加学生
 */
router.post('/students/new', function (req, res) {
  // 1. 获取表单数据
  // 2. 处理
  //    将数据保存到 db.json 文件中用以持久化
  // 3. 发送响应
  Student.save(req.body, function (err) {
    if (err) {
      return res.status(500).send('Server error.')
    }
    res.redirect('/students')
  })
})

/*
 * 渲染编辑学生页面
 */
router.get('/students/edit', function (req, res) {
  // 1. 在客户端的列表页中处理链接问题(需要有 id 参数)
  // 2. 获取要编辑的学生 id
  // 
  // 3. 渲染编辑页面
  //    根据 id 把学生信息查出来
  //    使用模板引擎渲染页面

  Student.findById(parseInt(req.query.id), function (err, student) {
    if (err) {
      return res.status(500).send('Server error.')
    }
    res.render('edit.html', {
      student: student
    })
  })
})

/*
 * 处理编辑学生
 */
router.post('/students/edit', function (req, res) {
  // 1. 获取表单数据
  //    req.body
  // 2. 更新
  //    Student.updateById()
  // 3. 发送响应
  Student.updateById(req.body, function (err) {
    if (err) {
      return res.status(500).send('Server error.')
    }
    res.redirect('/students')
  })
})

/*
 * 处理删除学生
 */
router.get('/students/delete', function (req, res) {
  // 1. 获取要删除的 id
  // 2. 根据 id 执行删除操作
  // 3. 根据操作结果发送响应数据

  Student.deleteById(req.query.id, function (err) {
    if (err) {
      return res.status(500).send('Server error.')
    }
    res.redirect('/students')
  })
})
  1. 把 router 导出
module.exports = router
//不要使用下面这种方式还要 .router 会麻烦一些。 上面是直接导出 
exports.router = router
  1. 原生封装(不推荐)
module.exports = function (app) {
  app.get('/students', function (req, res) {
    // readFile 的第二个参数是可选的,传入 utf8 就是告诉它把读取到的文件直接按照 utf8 编码转成我们能认识的字符
    // 除了这样来转换之外,也可以通过 data.toString() 的方式
    fs.readFile('./db.json', 'utf8', function (err, data) {
      if (err) {
        return res.status(500).send('Server error.')
      }

      // 从文件中读取到的数据一定是字符串
      // 所以这里一定要手动转成对象
      var students = JSON.parse(data).students

      res.render('index.html', {
        fruits: [
          '苹果',
          '香蕉',
          '橘子'
        ],
        students: students
      })
    })
  })

  app.get('/students/new', function (req, res) {

  })

  app.get('/students/new', function (req, res) {

  })

  app.get('/students/new', function (req, res) {

  })

  app.get('/students/new', function (req, res) {

  })

  app.get('/students/new', function (req, res) {

  })
}
三、应用路由模块

创建服务 做一些服务相关配置, 提供静态资源服务 。监听端口启动服务 .挂载路由

app.js :

  1. 导入模块,应用express
var express = require('express')//express 插件
var router = require('./router') //导入定义的路由模块
var bodyParser = require('body-parser') //post请求数据格式化插件
//应用express模块
var app = express()
  1. 资源配置路由模块挂载
//配置静态资源访问
app.use('/node_modules/', express.static('./node_modules/'))
app.use('/public/', express.static('./public/'))
//模版访问文件后缀格式
app.engine('html', require('express-art-template'))

// 配置模板引擎和 body-parser 一定要在 app.use(router) 挂载路由之前
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())

// 把路由容器挂载到 app 服务中
app.use(router)

app.listen(3000, function () {
  console.log('running 3000...')
})
  1. 模块导出
//导出模块,给上面原生方法封装使用的基础配置模块。 express中用不到了 
module.exports = app
四、student数据模块

这里只做异步操作示例,后期就是数据库操作模块。还可以细分每一个功能的模块

student.js:

/**
 * 封装异步 API
 */

var fs = require('fs')
var dbPath = {
  "students": [
    {
      "id": 1,
      "name": "张s",
      "gender": "0",
      "age": "24",
      "hobbies": "吃饭、打豆豆"
    },
    {
      "id": 2,
      "name": "张f",
      "gender": "0",
      "age": "23",
      "hobbies": "吃饭、睡觉"
    },
    {
      "id": 3,
      "name": "张3",
      "gender": "0",
      "age": "21",
      "hobbies": "睡觉、打豆豆"
    },
    {
      "id": 4,
      "name": "张三三",
      "gender": "0",
      "age": "22",
      "hobbies": "吃饭、睡觉、打豆豆"
    }
  ]
}
/**
 * 获取学生列表
 * @param  {Function} callback 回调函数
 */
exports.find = function (callback) {
    fs.readFile(dbPath, 'utf8', function (err, data) {
        if (err) {
            return callback(err)
        }
        callback(null, JSON.parse(data).students)
    })
}

/**
 * 根据 id 获取学生信息对象
 * @param  {Number}   id       学生 id
 * @param  {Function} callback 回调函数
 */
exports.findById = function (id, callback) {
    fs.readFile(dbPath, 'utf8', function (err, data) {
        if (err) {
            return callback(err)
        }
        var students = JSON.parse(data).students
        var ret = students.find(function (item) {
            return item.id === parseInt(id)
        })
        callback(null, ret)
    })
}

/**
 * 添加保存学生
 * @param  {Object}   student  学生对象
 * @param  {Function} callback 回调函数
 */
exports.save = function (student, callback) {
	//utf8编码自动是字符串不需要tostring
    fs.readFile(dbPath, 'utf8', function (err, data) {
        if (err) {
            return callback(err)
        }
        var students = JSON.parse(data).students

        // 添加 id ,唯一不重复
        student.id = students[students.length - 1].id + 1

        // 把用户传递的对象保存到数组中
        students.push(student)

        // 把对象数据转换为字符串
        var fileData = JSON.stringify({
            students: students
        })

        // 把字符串保存到文件中
        fs.writeFile(dbPath, fileData, function (err) {
            if (err) {
                // 错误就是把错误对象传递给它
                return callback(err)
            }
            // 成功就没错,所以错误对象是 null
            callback(null)
        })
    })
}

/**
 * 更新学生
 */
exports.updateById = function (student, callback) {
    fs.readFile(dbPath, 'utf8', function (err, data) {
        if (err) {
            return callback(err)
        }
        var students = JSON.parse(data).students

        // 注意:这里记得把 id 统一转换为数字类型
        student.id = parseInt(student.id)

        // 你要修改谁,就需要把谁找出来
        // EcmaScript 6 中的一个数组方法:find
        // 需要接收一个函数作为参数
        // 当某个遍历项符合 item.id === student.id 条件的时候,find 会终止遍历,同时返回遍历项
        var stu = students.find(function (item) {
            return item.id === student.id
        })

        // 这种方式你就写死了,有 100 个难道就写 100 次吗?
        // stu.name = student.name
        // stu.age = student.age

        // 遍历拷贝对象
        for (var key in student) {
            stu[key] = student[key]
        }

        // 把对象数据转换为字符串
        var fileData = JSON.stringify({
            students: students
        })

        // 把字符串保存到文件中
        fs.writeFile(dbPath, fileData, function (err) {
            if (err) {
                // 错误就是把错误对象传递给它
                return callback(err)
            }
            // 成功就没错,所以错误对象是 null
            callback(null)
        })
    })
}

/**
 * 删除学生
 */
exports.deleteById = function (id, callback) {
    fs.readFile(dbPath, 'utf8', function (err, data) {
        if (err) {
            return callback(err)
        }
        var students = JSON.parse(data).students

        // findIndex 方法专门用来根据条件查找元素的下标
        var deleteId = students.findIndex(function (item) {
            return item.id === parseInt(id)
        })

        // 根据下标从数组中删除对应的学生对象
        students.splice(deleteId, 1)

        // 把对象数据转换为字符串
        var fileData = JSON.stringify({
            students: students
        })

        // 把字符串保存到文件中
        fs.writeFile(dbPath, fileData, function (err) {
            if (err) {
                // 错误就是把错误对象传递给它
                return callback(err)
            }
            // 成功就没错,所以错误对象是 null
            callback(null)
        })
    })
}

源码地址

猜你喜欢

转载自blog.csdn.net/qq_39043923/article/details/89325561