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制作爬虫全过程
Dec 22 NodeJs
Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例
Jan 01 NodeJs
基于html5和nodejs相结合实现websocket即使通讯
Nov 19 NodeJs
详解nodejs微信公众号开发——5.素材管理接口
Apr 11 NodeJs
NodeJs的fs读写删除移动监听
Apr 28 NodeJs
Nodejs进阶之服务端字符编解码和乱码处理
Sep 04 NodeJs
利用nodeJs anywhere搭建本地服务器环境的方法
May 12 NodeJs
Linux Centos7.2下安装nodejs&amp;npm配置全局路径的教程
May 15 NodeJs
nodejs中express入门和基础知识点学习
Sep 13 NodeJs
nodejs中用npm初始化来创建package.json的实例讲解
Oct 10 NodeJs
详解NodeJS Https HSM双向认证实现
Mar 12 NodeJs
nodejs中实现用户注册路由功能
May 20 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 smarty模版引擎中变量操作符及使用方法
2009/12/11 PHP
php 文章采集正则代码
2009/12/28 PHP
thinkPHP3.2简单实现文件上传的方法
2016/05/16 PHP
php中序列化与反序列化详解
2017/02/13 PHP
JavaScript中通过闭包解决只能取得包含函数中任何变量最后一个值的问题
2010/08/12 Javascript
实用的Jquery选项卡TAB示例代码
2013/08/28 Javascript
js获取iframe中的window对象的实现方法
2016/05/20 Javascript
Bootstrap中文本框的宽度变窄并且加入一副验证码图片的实现方法
2016/06/23 Javascript
jQuery 自定义下拉框(DropDown)附源码下载
2016/07/22 Javascript
JS 滚动事件window.onscroll与position:fixed写兼容IE6的回到顶部组件
2016/10/10 Javascript
vue脚手架vue-cli的学习使用教程
2017/06/06 Javascript
jQuery扩展_动力节点Java学院整理
2017/07/05 jQuery
vue-lazyload图片延迟加载插件的实例讲解
2018/02/09 Javascript
使用bootstrap实现下拉框搜索功能的实例讲解
2018/08/10 Javascript
解决vue 界面在苹果手机上滑动点击事件等卡顿问题
2018/11/27 Javascript
详解Vue中watch对象内属性的方法
2019/02/01 Javascript
JS回调函数深入理解
2019/10/16 Javascript
解决node.js含有%百分号时发送get请求时浏览器地址自动编码的问题
2019/11/20 Javascript
[56:01]2018DOTA2亚洲邀请赛 3.31 小组赛 B组 Effect vs EG
2018/03/31 DOTA
[02:17]快乐加倍!DOTA2食人魔魔法师至宝+迎霜节活动上线
2019/12/22 DOTA
python打开网页和暂停实例
2014/09/30 Python
Python中的生成器和yield详细介绍
2015/01/09 Python
Python最长公共子串算法实例
2015/03/07 Python
Python整型运算之布尔型、标准整型、长整型操作示例
2017/07/21 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
2017/12/20 Python
python实现简单遗传算法
2018/03/19 Python
Django 对象关系映射(ORM)源码详解
2019/08/06 Python
python 并发编程 阻塞IO模型原理解析
2019/08/20 Python
Python socket聊天脚本代码实例
2020/01/02 Python
VSCode 自定义html5模板的实现
2019/12/05 HTML / CSS
茶叶生产计划书
2014/01/10 职场文书
商场拾金不昧表扬信
2014/01/13 职场文书
家长学校工作方案
2014/05/07 职场文书
2014年党风廉政工作总结
2014/12/03 职场文书
通知怎么写?
2019/04/17 职场文书
5行Python代码实现一键批量扣图
2021/06/29 Python