nodejs教程之制作一个简单的文章发布系统


Posted in NodeJs onNovember 21, 2014

前言

我们今天就来做一个简单的新闻发布系统,系统第一阶段不需要太难,主要有以下功能

① 新闻类型管理

② 新闻管理(具有图片上传功能)

③ 新闻浏览

功能虽然不多,但是也涵盖很多基本操作了,程序不过增删查改嘛,外加上传附件,够了。于是开始我们今天的学习吧

准备工作

根据昨天的折腾后,我们已经有了nodeJS与mongoDB环境了,现在直接新建工程文件与数据库文件即可

第一步,打开命令符切换到D盘后输入

D:\>express -e news

于是系统会自动开开心心构建基本环境

nodejs教程之制作一个简单的文章发布系统

很明显,里面很多模块依赖没有,这个时候将昨天的package.json直接考过来:

{

  "name": "application-name",

  "version": "0.0.1",

  "private": true,

  "scripts": {

    "start": "node app.js"

  },

  "dependencies": {

    "express": "3.4.8",

    "ejs": "*",

    "mongodb": "*"

  }

}

然后切换到项目目录下:

nmp install

依赖文件全部搞下来了,然后我们输入

D:\news>node app

Express server listening on port 3000

于是,我们的程序高高兴兴的运行起来了,打开网址一看,确实没问题

PS:这里有个问题需要注意,我们下载下来的文件不是UTF-8编码,所以中文可能有乱码,文件编码需要各位自己统一

程序跑起来了就需要数据库相关的配置了

① 首先在mongoDB目录中新建news文件夹

② 为项目新增配置文件settings.js

module.exports = {

  cookieSecret: 'myNews',

  db: 'news',

  host: 'localhost'

};

③ 新建models目录,新建db.js

var settings = require('../settings'),

    Db = require('mongodb').Db,

    Connection = require('mongodb').Connection,

    Server = require('mongodb').Server;

module.exports = new Db(settings.db, new Server(settings.host, Connection.DEFAULT_PORT), { safe: true });

④ 在桌面新建news.bat程序

d:\mongodb\bin\mongod.exe -dbpath d:\mongodb\news

以后要启动数据库,只需要运行他即可,如此,我们初步的准备工作基本结束

但是这里有两个比较烦的事情,一个是每次要启动news程序很烦,二个是修改任何东西都需要重启,于是我们这里先解决这两个问题

① 在桌面新建news_app.bat,以后运行他就可以启动程序了

node d:\news\app

② supervisor为一进程保护程序,我们可以使用他帮我们重启程序,首先按照,然后调整我们的node_app.bat

supervisor d:\news\app

当然之前需要安装:

npm install -g supervisor

这个样子后,修改了文件就不需要手动重启了(需要将news_app放到项目目录下),于是准备工作到此为止

项目结构

第一步结束后,我们就需要思考下项目结构了

① 首页为index这里将列出所有新闻类型以及对于新闻条目

② 各个新闻条目拥有编辑/删除/查看 三个按钮

③ 首页具有增加新闻按钮(增加时候可上传图片)

基本功能如上

于是,我们去掉app里面的路由功能,将路由全部放到index里面

//将路由功能放入index

//app.get('/', routes.index);

//app.get('/users', user.list);

routes(app);
module.exports = function (app) {

  //主页,现在也是首页

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

    res.render('index', { title: 'Express' });

  });

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

    res.send('增加新闻请求');

  });

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

    res.send('删除新闻请求');

  });

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

    res.send('查看新闻请求');

  });

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

    res.send('修改新闻请求');

  });

};

第一步简单如此,因为增加新闻应该有单独的页面,而具体点击增加按钮又会有其他处理,所以内部还得细分各个请求,现在规定如下:

/ 默认页面,该页面显示所有类型以及新闻,并带有删除按钮

/add 进入添加新闻页面

/addNews 添加新闻具体post请求地址(点击按钮时候的响应)

/delete 删除新闻请求

/view 具体新闻查询

于是稍微修改下上述路由:

module.exports = function (app) {

  //主页,现在也是首页

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

    res.render('index', { title: 'Express' });

  });

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

    res.send('添加新闻页面');

  });

  app.post('/addNews', function (req, res) {

    res.send('处理添加新闻请求');

  });

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

    res.send('删除新闻请求');

  });

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

    res.send('查看新闻请求');

  });

};

于是我们需要新建几个模板组织我们的网页,这里我们先不分离头尾只要最简单的页面即可

新增add与view两个模板文件,暂时表现与index.ejs一致,并且修改导航相关

module.exports = function (app) {

  //主页,现在也是首页

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

    res.render('index', { title: 'Express' });

  });

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

    res.render('add', { title: '添加新闻页面' });

  });

  app.post('/addNews', function (req, res) {

    res.send('处理添加新闻请求');

  });

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

    res.send('删除新闻请求');

  });

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

    res.render('view', { title: '查看新闻请求' });

  });

};

至此项目结构结束

数据操作

整体结构出来后,我们就需要进行数据操作了:

① 增加数据(增加新闻)

② 展示数据(展示新闻)

③ 删除数据(删除新闻)

本来还涉及到类型操作的,但是做着做着给搞没了,暂时不管他吧,因为首次做容易迷糊

增加新闻

这里,我们就不使用表单提交了,我们用ajax......这里顺便引入zepto库,于是我们的页面成了这样

<!DOCTYPE html>

<html>

<head>

    <title>

        <%= title %></title>

    <link rel='stylesheet' href='/stylesheets/style.css' />

    <script src="javascripts/zepto.js" type="text/javascript"></script>

</head>

<body>

    <h1>

        <%= title %></h1>

    <div>

        标题:<input type="text" id="title" />

    </div>

    <div>

        内容:<textarea id="content"></textarea>

    </div>

    <div>

        <input type="button" type="button" id="ok" value="添加新闻" />

    </div>

    <script type="text/javascript">

        $(document).ready(function () {

            $('#ok').click(function () {

                var param = {};

                param.title = $('#title').val();

                param.content = $('#content').val();

                $.post('/addNews', param, function () {

                    console.log('添加成功');

                });

            });

        });

    </script>

</body>

</html>

nodejs教程之制作一个简单的文章发布系统nodejs教程之制作一个简单的文章发布系统

虽然现在还没有请求响应程序,所以数据并不会被处理,另外我们这里的附件也没有(现在附件只允许一个好了),于是再修改下代码,加入图片:

PS:比较麻烦的是图片经过ajax处理有点麻烦,所以我们这里乖乖的换回form操作算了,不然又要搞多久......

<html>

<head>

    <title>

        <%= title %></title>

    <link rel='stylesheet' href='/stylesheets/style.css' />

</head>

<body>

    <h1>

        <%= title %></h1>

    <form enctype="multipart/form-data" method="post"  action="/addNews">

    <div>

        标题:<input type="text" id="title" name="title" />

    </div>

    <div>

        图片:<input type="file" id="pic" name="pic" />

    </div>

    <div>

        内容:<textarea id="content" name="content"></textarea>

    </div>

    <div>

        <input  type="submit" id="ok" value="添加新闻" />

    </div>

    </form>

</body>

</html>

这个样子就不需要过多的考虑附件问题,先暂时如此吧,现在先处理请求程序,这里先在public里面新建news文件夹用于存储其图片

model

在models文件夹新增news.js文件,为其构建实体,并赋予新增查询相关操作:

var mongodb = require('./db');
function News(title, content, pic) {

  this.title = title;

  this.content = content;

  this.pic = pic;//保存存储路径

};

module.exports = News;

//存储数据

News.prototype = {

  save: function (callback) {

    var date = new Date();

    var time = {

      date: date,

      year: date.getFullYear(),

      month: date.getFullYear() + "-" + (date.getMonth() + 1),

      day: date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(),

      minute: date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " +

      date.getHours() + ":" + (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())

    }

    //数据存储对象

    var news = {

      title: this.title,

      content: this.content,

      pic: this.pic, //图片处理最后来说,现在先乱存

      time: time

    };

    //打开数据连接,打开就是一个回调......

    mongodb.open(function (err, db) {

      //错误就退出

      if (err) {

        return callback(err);

      }

      //打开news集合

      db.collection('news', function (err, collection) {

        if (err) {

          mongodb.close();

          return callback(err);

        }

        //写入集合(写入数据库)

        collection.insert(news, { safe: true }, function (err) {

          return callback(err);

        });

        callback(null);//err为null

      });

    });

  }

};

于是,写入数据库的程序就有了,这里我们来试试能不能插入数据库,当然需要修改路由处的程序

PS:路由处当然不能写过多逻辑代码,这个文件以后还得分离

这个时候/addNews里面的逻辑需要改变

app.post('/addNews', function (req, res) {

  var title = req.body.title;

  var content = req.body.content;

  var pic = req.body.pic;

  var news = new News(title, content, pic)

  news.save(function (err, data) {

    res.send(data);

  })

});

nodejs教程之制作一个简单的文章发布系统

查询下,问题不大,现在要解决的就是附件问题了

上传图片

上传图片功能express本身就支持了,express通过bodyParser解析请求体,然后便可通过他上传文件了,其内部使用了formidable

这里将app.js里面的app.use(express.bodyParser())改为:

app.use(express.bodyParser({ keepExtensions: true, uploadDir: './public/news' }));

打开index.js,在前面加一行代码:

fs = require('fs'),

修改一下index文件:

app.post('/addNews', function (req, res) {

  for (var i in req.files) {

    if (req.files[i] == 0) {

      //同步方式删除一个文件

      fs.unlinkSync(req.files[i].path);

      console.log('success removed an empty file');

    } else {

      var path = './public/news/' + req.files[i].name;

      // 使用同步方式重命名一个文件

      fs.renameSync(req.files[i].path, path);

      console.log('sunccess renamed a file');

    }

  }

//    var title = req.body.title;

//    var content = req.body.content;

//    var pic = req.body.pic;

//    var news = new News(title, content, pic)

//    news.save(function (err, data) {

//      res.send(data);

//    })

});

这个时候选取文件后点击添加新闻,我们的文件就上传上去了

nodejs教程之制作一个简单的文章发布系统

这个时候,我只需要将文件名记录在数据库即可,文件目录里面就有图片了

app.post('/addNews', function (req, res) {

  var pic = null;

  for (var i in req.files) {

    if (req.files[i] == 0) {

      //同步方式删除一个文件

      fs.unlinkSync(req.files[i].path);

      console.log('success removed an empty file');

    } else {

      var path = './public/news/' + req.files[i].name;

      // 使用同步方式重命名一个文件

      fs.renameSync(req.files[i].path, path);

      console.log('sunccess renamed a file');

    }

    pic = req.files[i].name;

  }

  var title = req.body.title;

  var content = req.body.content;

  var news = new News(title, content, pic)

  news.save(function (err, data) {

    res.send(data);

  })

  res.send('<a href="./">请求成功,返回首页</a>');

});

nodejs教程之制作一个简单的文章发布系统

数据库中有数据了,我们目录也有文件了,现在只需要将数据读出来了

PS:放假兄弟们催的凶,要出去喝酒了

读取数据

第二步当然是读取数据,首先是首页的数据读取:

var mongodb = require('./db');

function News(title, content, pic) {

  this.title = title;

  this.content = content;

  this.pic = pic;//保存存储路径

};

module.exports = News;

//存储数据

News.prototype = {

  save: function (callback) {

    var date = new Date();

    //数据存储对象

    var news = {

      title: this.title,

      content: this.content,

      pic: this.pic, //图片处理最后来说,现在先乱存

      date: date

    };

    //打开数据连接,打开就是一个回调......

    mongodb.open(function (err, db) {

      //错误就退出

      if (err) {

        return callback(err);

      }

      //打开news集合

      db.collection('news', function (err, collection) {

        if (err) {

          mongodb.close();

          return callback(err);

        }

        //写入集合(写入数据库)

        collection.insert(news, { safe: true }, function (err) {

          return callback(err);

        });

        callback(null); //err为null

      });

    });

  }

};

//读取文章及其相关信息

News.get = function (id, callback) {

  //打开数据库

  mongodb.open(function (err, db) {

    if (err) {

      return callback(err);

    }

    db.collection('news', function (err, collection) {

      if (err) {

        mongodb.close();

        return callback(err);

      }

      var query = {};

      if (id) {

        query.id = id;

      }

      //根据 query 对象查询文章

      collection.find(query).sort({

        date: -1

      }).toArray(function (err, data) {

        mongodb.close();

        if (err) {

          return callback(err); //失败!返回 err

        }

        callback(null, data); //成功!以数组形式返回查询的结果

      });

    });

  });

};

news.js
<!DOCTYPE html>

<html>

<head>

    <title>

        <%= title %></title>

    <link rel='stylesheet' href='/stylesheets/style.css' />

</head>

<body>

    <h1>

        <%= title %></h1>

    <ul>

        <%for(var k in data) { %>

        <li>

            <div>

               标题: <%=data[k].title %></div>

            <div>

              内容:  <%=data[k].content%></div>

              <div>

              附件:<img src="news/<%= data[k].pic%>" /></div>

              </div>

              <div>

              <a href="/delete?id=<%=data[k] %>">删除</a>

              </div>

              <hr/>

        </li>

        <%} %>

    </ul>

</body>

</html>

nodejs教程之制作一个简单的文章发布系统

结语

好了,文章发布系统的制作就先到这里了,以后我们再慢慢增加功能,慢慢做美化。

NodeJs 相关文章推荐
Nodejs sublime text 3安装与配置
Jun 19 NodeJs
Google官方支持的NodeJS访问API,提供后台登录授权
Jul 29 NodeJs
nodejs调用cmd命令实现复制目录
May 04 NodeJs
NodeJs中的VM模块详解
May 06 NodeJs
NodeJs——入门必看攻略
Jun 27 NodeJs
浅谈Nodejs中的作用域问题
Dec 26 NodeJs
详解nodejs微信jssdk后端接口
May 25 NodeJs
NodeJS加密解密及node-rsa加密解密用法详解
Oct 12 NodeJs
NodeJS读取分析Nginx错误日志的方法
May 14 NodeJs
nodejs和react实现即时通讯简易聊天室功能
Aug 21 NodeJs
NodeJS有难度的面试题(能答对几个)
Oct 09 NodeJs
Nodejs实现WebSocket代码实例
May 19 NodeJs
nodejs教程之环境安装及运行
Nov 21 #NodeJs
nodejs教程之异步I/O
Nov 21 #NodeJs
nodejs教程之入门
Nov 21 #NodeJs
nodejs 提示‘xxx’ 不是内部或外部命令解决方法
Nov 20 #NodeJs
nodejs开发环境配置与使用
Nov 17 #NodeJs
Nodejs全栈框架StrongLoop推荐
Nov 09 #NodeJs
初始Nodejs
Nov 08 #NodeJs
You might like
php定义一个参数带有默认值的函数实例分析
2015/03/16 PHP
使用symfony命令创建项目的方法
2016/03/17 PHP
javascript编程起步(第二课)
2007/02/27 Javascript
Mootools 1.2教程 Fx.Morph、Fx选项和Fx事件
2009/09/15 Javascript
Javascript 两个窗体之间传值实现代码
2009/09/25 Javascript
使用jQuery清空file文件域的解决方案
2013/04/12 Javascript
javascript相等运算符与等同运算符详细介绍
2013/11/09 Javascript
关闭浏览器输入框自动补齐 兼容IE,FF,Chrome等主流浏览器
2014/02/11 Javascript
JS使用replace()方法和正则表达式进行字符串的搜索与替换实例
2014/04/10 Javascript
谷歌地图打不开的解决办法
2014/08/07 Javascript
javascript关于运动的各种问题经典总结
2015/04/27 Javascript
vue.js学习笔记之绑定style样式和class列表
2016/10/31 Javascript
Bootstrap 模态框实例插件案例分析
2016/12/28 Javascript
jQuery实现扑克正反面翻牌效果
2017/03/10 Javascript
详解使用webpack打包编写一个vue-toast插件
2017/11/08 Javascript
基于nodejs的微信JS-SDK简单应用实现
2019/05/21 NodeJs
微信小程序实现类似微信点击语音播放效果
2020/03/30 Javascript
JavaScript实现京东放大镜效果
2019/12/03 Javascript
[46:20]TFT vs Secret Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
[01:32:10]NAVI vs VG Supermajor 败者组 BO3 第一场 6.5
2018/06/06 DOTA
Python continue语句用法实例
2014/03/11 Python
python两种遍历字典(dict)的方法比较
2014/05/29 Python
Python线程指南分享
2019/11/19 Python
python flask中动态URL规则详解
2019/11/22 Python
Python利用全连接神经网络求解MNIST问题详解
2020/01/14 Python
python实现查找所有程序的安装信息
2020/02/18 Python
如何利用Python 进行边缘检测
2020/10/14 Python
Python操控mysql批量插入数据的实现方法
2020/10/27 Python
Photobook澳大利亚:制作相片书,婚礼卡,旅行相簿
2017/01/12 全球购物
毕业生求职简历中的自我评价
2013/10/18 职场文书
编辑找工作求职信范文
2013/12/16 职场文书
创业计划书的内容步骤和要领
2014/01/04 职场文书
打造完美自荐信
2014/01/24 职场文书
法定代表人资格证明书
2015/06/18 职场文书
学校运动会加油词
2015/07/18 职场文书
Python Django搭建文件下载服务器的实现
2021/05/10 Python