Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js 入门:Express + Mongoose 基础使用 #21

Open
lin-xin opened this issue Jul 29, 2017 · 4 comments
Open

Node.js 入门:Express + Mongoose 基础使用 #21

lin-xin opened this issue Jul 29, 2017 · 4 comments
Labels

Comments

@lin-xin
Copy link
Owner

lin-xin commented Jul 29, 2017

前言

Express 是基于 Node.js 平台的 web 应用开发框架,在学习了 Node.js 的基础知识后,可以使用 Express 框架来搭建一个 web 应用,实现对数据库的增删查改。

数据库选择 MongoDB,它是一个基于分布式文件存储的开源数据库系统,Mongoose 是 MongoDB 的对象模型工具,可以在异步环境里工作。

接下来就使用 Express + Mongoose 来实现简单的增删查改,在实现的过程中来学习 Express 和 Mongoose 的基础知识。

准备

既然是基于 Node.js 的框架,那么肯定需要装 node.js,还有 MongoDB,网上有很多安装教程。然后使用 express-generator 来快速生成一个 Express 项目。那么先安装一下 express-generator

npm install -g express-generator

然后初始化一个名为 express-demo 的项目

express express-demo

目前 Express 已经发布到了 4.x 版本,接下来也是基于这个版本来实现的。

cd express-demo
npm install
npm start

浏览器打开 http://localhost:3000 ,就可以看到已经可以访问了。

目录

├─bin/      // 启动文件
├─public/   // 资源文件
├─routes/   // 路由
├─views/    // 视图
├─app.js
└─package.json

初始化的项目目录简单明了,接下来我们来看看 app.js 里是写了什么。

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

这是设置模板引擎,使用了 jade 模板引擎,views/ 目录下都是 .jade 格式文件,这种写法我并不熟悉,那么来改一下,改成 ejs 引擎,.html 格式的视图文件。(需要 npm 安装 ejs 模块)

var ejs = require('ejs');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('html', ejs.__express);
app.set('view engine', 'html');

实现

以上准备都好了之后,我们就来看看如何实现用户信息的增删查改。这里我们先把视图和路由搭建起来,能访问页面之后再来实现数据库操作的功能。

用户列表

在 view/ 视图目录下创建以下文件: UserList.html

<!DOCTYPE html>
<html>
<head>
    <title>用户列表页面</title>
</head>
<body>
    <table>
        <tr>
            <th>用户名</th>
            <th>邮箱</th>
            <th>操作</th>
        </tr>
        <% for(var i in user){ %>
            <tr>
                <td><%= user[i].username %></td>
                <td><%= user[i].email %></td>
                <td>
                    <div>
                        <a href="/users/detail/<%= user[i]._id %>"> 查看 </a>
                        <a href="/users/edit/<%= user[i]._id %>"> 编辑 </a>
                        <a href="#" class="del" data-id="<%= list[i]._id %>"> 删除 </a>
                    </div>
                </td>
            </tr>
        <% } %>
    </table>
</body>
</html>

<% %> 就是 ejs 模板引擎的语法,user 是在路由渲染页面的时候传过来的,它是如何传的,待会再看。
接下来实现上面视图对应的路由,项目中默认已经给我们生成了两个路由。在 routes/ 路由目录下已经有了两个路由文件:index.js 和 users.js。

app.js 中,已经帮我们设置好了这两个路由:

var index = require('./routes/index');
var users = require('./routes/users');
app.use('/', index);
app.use('/users', users);

只要浏览器访问 http://localhost:3000/users ,就能访问到 users 对应的页面了。我们来看看路由里 users.js 是如何写的。

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;

express.Router 类创建模块化、可挂载的路由句柄。我们修改上面代码来创建用户列表的路由 users/list

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

router.get('/list', function(req, res, next) {
  var list = [{_id: 1, username: 'linxin', email: '123123@qq.com'}];
  res.render('UserList',{
      user: list
  })
});

module.exports = router;

还记得在 UserList.html 视图中的 user 变量吗,这里用到了 res.render() 响应方法,功能就是渲染视图模板,第一个参数为视图文件名,第二个参数为对象,用于向模板中传递数据,user 就是在这里传过去的。更改完路由之后重启服务器,访问 http://localhost:3000/users/list 就可以看到用户列表页面了。

但是这用户信息是写死的,要怎么从数据库中读取呢?

连接数据库

我们这里用到了 Mongoose,需要先安装 npm install mongoose -S 。安装之后在项目中引入并连接到数据库 userdb

var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/userdb', {useMongoClient: true});

连接成功之后,定义一个 Schema,它一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力。

var userSchema = new mongoose.Schema({
    username: String,
    email: String
})

这里的 userSchema 还不能对数据库进行操作,只是定义了数据模型属性 username, email 为字符串类型。需要将该 Schema 发布为 Model,Model 是由 Schema 发布生成的模型,具有抽象属性和行为的数据库操作对。

var model = mongoose.model('user', userSchema);

最后 model 就可以对数据库进行操作了,把上面的代码封装成 userModel.js 到根目录下新建一个 models/ 目录下面,用 module.exports = model; 将 model 暴露出来供其他文件使用。

在 user.js 路由文件里,我们来引入 userModel.js 进行数据库操作。

var userModel = require('../models/userModel.js');

router.get('/list', function(req, res, next) {
  userModel.find(function(err, data){
    if(err){ return console.log(err) }
    res.render('UserList',{
      user: data
    })
  })
});

这里使用 userModel.find() 查询到所有用户。但是现在数据库里还是空的,我们来新增一个添加用户页面向数据库里插入数据。

添加用户

在 views/ 目录下新建 UserAdd.html 添加用户视图

<!DOCTYPE html>
<html>
<head>
    <title>用户编辑页面</title>
</head>
<body>
    <form action="/users/add" method="post">
        <input type="text" name="username" value="">
        <input type="email" name="email" value="">
        <button type="submit">submit</button>
    </form>
</body>
</html>

在 user.js 路由文件里来添加对应视图的路由

router.get('/add', function(req, res, next) {
  res.render('UserAdd');
});

这是渲染视图页面的路由,我们需要添加一个 post 方法的路由,在点击提交按钮的时候,把数据存进数据库里。

router.post('/add', function(req, res, next) {
  var newUser = new userModel({
    username: req.body.username,
    email: req.body.email
  })
  newUser.save(function(err, data){
    if(err){ return console.log(err) }
    res.redirect('/users/list');
  })
});

这里使用 new userModel() 创建了一个 Entity,它是由 Model 创建的实体,它的操作也会影响数据库。newUser 调用 save() 方法将数据保存到数据库中。然后 res.redirect() 将页面重定向到用户列表页面,这时就可以看到我们新增的用户显示在列表中了。接下来我们看看如何来编辑用户信息。

编辑用户

依然是创建相应的用户编辑视图:UserEdit.html

<!DOCTYPE html>
<html>
<head>
    <title>用户编辑页面</title>
</head>
<body>
    <form action="/users/update" method="post">
        <input type="hidden" name="id" value="<%= user._id %>">
        <input type="text" name="username" value="<%= user.username %>">
        <input type="email" name="email" value="<%= user.email %>">
        <button type="submit">update</button>
    </form>
</body>
</html>

添加对应的路由:/users/edit/:id 来渲染视图,/users/update 来修改数据库数据

router.get('/edit/:id', function (req, res, next) {
  var id = req.params.id;
  userModel.findOne({_id: id}, function (err, data) {
    res.render('UserEdit', {
      user: data
    })
  })
});
router.post('/update', function (req, res, next) {
  var id = req.body.id;
  userModel.findById(id, function (err, data) {
    if(err){ return console.log(err); }
    data.username = req.body.username;
    data.email = req.body.email;
    data.save(function(err){
      res.redirect('/users/list');
    })
  })
});

userModel.findOne() 会根据查询条件 {_id: id} 查询到对应的一条数据,那么同理,查看用户详情的实现也是如此,只是渲染你到另外一个模板而已,这里就不重复写了;userModel.findById() 查询到 data 对象,该对象也属于 Entity,有 save() 操作。req.body.username 就可以获取到我们修改后的 username,修改 data 对象之后调用 save() 方法保存到数据库中。接下来看看如何删除用户吧。

删除用户

在用户列表中,点击删除按钮,就把该用户从数据库中给删除了,不需要视图,那直接写路由吧。

router.delete('/del', function (req, res) {
  var id = req.query.id;
  userModel.remove({_id: id}, function (err, data) {
    if(err){ return console.log(err); }
    res.json({code: 200, msg: '删除成功'});
  })
})

点击按钮,发送删除的请求,那我们可以使用 ajax 来实现。在用户列表页面引入 jquery,方便我们操作。然后添加 ajax 请求

$('.del').on('click',function(){
    var id = $(this).data('id');
    $.ajax({
        url: '/users/del?id='+id,
        type: 'delete',
        success: function (res) { console.log(res); }
    })
})

重启服务器,进入 users/list,点击删除按钮,如果看到控制台中已经打印了 {code: 200, msg: '删除成功'} ,表示已经成功删除了,这时我们刷新页面,看看列表中确实已经不存在该用户了。

代码地址: express-demo

总结

通过对用户的增删查改,学习如何写路由已经如何操作数据库。我们来总结一下:

  1. 定义 Schema,由 Schema 发布 Model 来操作数据库。
  2. Model 创建的实体 Entity,可以调用 save() 方法将数据保存到数据库中。
  3. Model.find() 方法查询到该 Schema 下的所有数据,findOne() 根据条件查询数据,findById() 根据 id 查询数据。
  4. Model.remove() 删除数据。
@noobalex
Copy link

作者能否出个整合vue框架的Demo?

@lin-xin
Copy link
Owner Author

lin-xin commented Jul 31, 2017

@eddiebai 已经在准备结合 vue 的服务端渲染框架 nuxt.js 做一个,欢迎关注

@Rudy24
Copy link

Rudy24 commented Dec 23, 2017

在 view/ 视图目录下创建以下文件: UserList.html 中 删除 list[i]_id 写错了,应该是user[i]._id

@SSShooter
Copy link

想问一下登陆之后的数据权限问题你怎么处理?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants