express搭建简易后台(前端必备)

3,399 阅读4分钟

前言

之前一直写前端,了解过后端但是没有具体实现过接口。最近在学node,所以用express搭建了一个简易的后台,实现了登录注册等功能,写完这个Demo之后自己对后端的理解加深了一个层次,也了解了之前前后端没有分离的MVC模式的模板渲染具体细节。

这个demo是一个很简单的评论系统,用户注册登录之后发布评论,页面展示评论。其实可扩展性还是很高的,目前存储数据用的文件之后可以改为MongoDB或者Mysql,还可以添加删除、查找功能,这可以做一个论坛或者商城的评论组件。

本篇文章讲一下实现思路以及过程中遇到的问题,一起学习吧。(源码见文章末尾)

效果图

因为是重点是在后台接口,所以前端样式很简单

项目目录

我用的express快速搭建生成的,生成好了之后自动在app.js文件中导入依赖项

# 安装express-generator
$ npm install express-generator -g

# 快速搭建项目骨架
$ express -e proName

目录细节

  • public ---静态资源
    • data.json -----评论数据以及用户数据
    • img、js、css
  • routes -----路由
    • index.js ----- 页面路由
    • data.js ----- 数据接口路由
  • views ----- 页面模板
  • app.js ------ 项目入口

思路

我们将页面部署在localhost:3000端口,浏览器根据index.js里的页面路由请求相应页面。页面所有和数据有关的操作接口,比如用户注册、发布评论等放在data.js中,将路由分为页面路由和数据路由,这样结构更清晰一些。

view用的ejs,渲染方式为下面的第二种,这和我们平时的html不太一样,ejs是js的模板库,就好像Java的jsp一样。

渲染数据有两种方式:

  • 就像上一篇文字聊天室那样直接将html发送给客户端,然后通过ajax获取数据让js来渲染
  • 将数据导入模板在后端渲染好了将渲染好的html发送给客户端,这种方式是以前所谓的前后端不分离。

代码讲解

评论系统的逻辑是:用户注册登录之后发布评论,评论展示在面板上。

// app.js
// some code
app.use('/', index);  // 当请求为localhost:3000/时用index.js路由
app.use('/data', data);  // 当请求为localhost:3000/data时用路由data.js
// some code

页面路由

根据该路由定向页面,res.render(page, data); -->用data数据渲染page模板。

// index.js
var fs = require('fs');  // 导入会使用到的模块
var express = require('express');
var router = express.Router();
var path = './public/data/';

/* 当请求url为localhost:3000时渲染home.ejs返回给浏览器 */
router.get('/', function(req, res, next) {
  fs.readFile(path+'data.json', (err, data) => { // 读取文件,并执行回调函数
    if (err) {
      return res.send({
        status:0,
        info: 'fail.....'
      });
    }
    var obj = JSON.parse(data.toString());  // 返回数据
    return res.render('home', {  //否则,如果读取成功,渲染模板edit.jsp,返回数据obj
      data: {
        arr: obj,
        name: req.cookies.username //登录用户储存在cookie中
      }
    });
  });
}); 

router.get('/login', function(req, res, next) {
  res.cookie('username', '');
  res.render('login', {});
});

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

router.get('/send', function(req, res, next) {
  res.render('send', {
    data: {
      name: req.cookies.username
    }
  });
});

module.exports = router;

在我们的模板中我们是用a标签进行跳转的,比如

<a href="/login">登录</a>  ---> 点击跳转到登录界面

数据路由

以发布评论举例,当用户点击发布按钮时会发出一个ajax请求

// send.js
$.ajax({
            type: 'POST',
            url: '/data/write',
            dataType: 'json',  // 预期服务器的返回类型
            data: obj,  // 将用户发送的评论作为数据传输出去
            success: function(data) {
                // some code
            },
            error: function() {
                alert('发布评论失败,请重试!');
            }
        }); 

相应的接收post请求的后台接口:

// data.js
//...some code
/* 发布评论 */
router.post('/write', function(req, res, next) {
    if(!req.cookies.username) {  // 如果用户未登录
        return res.send({
          status: 2,
          info: '请先登录!'
        });
    }

  var obj = {
    username: req.cookies.username, 
    content: req.body.content
  };
  fs.readFile(path+'data.json', (err, data) => { // 读取文件,并执行回调函数
    if (err) {
      return res.send({
        status:0,
        info: '读取评论数据失败'
      });
    }

    var arr = JSON.parse(data.toString());  // 获取文件数据
    arr.splice(0, 0, obj); // 插入新评论数据
    var newData = JSON.stringify(arr);  // 转为json

    // 将用户传来的评论加入数据库(data.json),因为我用的文件存储,后期可以改为MongoDB或mysql
    fs.writeFile(path+'data.json', newData, function(err){
        if(err){
            return res.send({
                status:0,
                info: '添加评论数据失败'
            });
        }
        return res.send({
            status:1,
            info: obj
        });
    }); 
  });
});
// some code

这里可能有一个疑问:

  • /data/write接口只是将传来的数据存储到了文件,data.json的数据更新之后新数据怎么渲染上home.ejs的?
    先理一下index.js,当路由为'/'时我们将从data.json中读取的数据渲染到home.ejs模板,当我们发布评论之后,通过/data/write接口将新评论写入data.json,写入成功后返回data,data.status=1。在send.js的ajax的success中,当data.status=1时我们就刷新页面。home.ejs自然就会重新渲染了。
  • 关于模板渲染不得不说的:
    浏览器每向服务器请求一次,通俗的说也就是页面每刷新一次,模板就会重新渲染一次。

结语

  • 这个项目采用的MVC,M是数据(data.json和user.json),V(view)是ejs模板,C(路由)负责渲染模板与数据。
  • 源码地址:windlany/express-comment,可以fork下来根据自己的需求改改,觉得不错请给我一个star。