Nodejs完成一个待办事项的实例教程

来源:互联网 发布:做淘宝加盟要多少钱 编辑:程序博客网 时间:2024/06/08 15:41

这是一个用Node完成的待办事项的Demo,支持手机端和PC浏览器端同时查看。下载地址:https://github.com/yangfanacc/Todo 在线查看效果可以访问这个网址:http://123.56.44.245:3460 效果图如下:首先介绍一个这个待办事项示例项目的搭建环境:

    1.Nodejs版本:v0.10.35    2.Mongodb(使用Mongoose连接Mongodb数据库)    3.前台使用了国内比较好用的开源框架[Amaze](http://amazeui.org/)

项目的结构二级截图如下:

项目思路

首先,需要一个网址可以用来访问我们的待办事项首页(对数据库的读操作)。然后我们需要有添加和删除待办事项的对数据库的增加和删除(更新)操作。其实,也就这么多了,很简单的是不是?不过这里我们可不是真的删除,因为我们有可能需要保存我们的待办事项历史,大家可以访问这个网址:http://123.56.44.245:3460/all 是的,我们在删除待办事项的时候,是需要一个bool参数在数据库中,只是把数据变为false不在读取,而不是真的删除。这和我们使用腾讯的QQ空间是一样的效果嘛,哈哈:)

第一步

我们需要确定使用那些类库,我们这里使用的类库如下:

    1.body-parser      2.cookie-parser      3.debug      4.ejs      5.express      6.mongoose      7.morgan      8.serve-favicon

大家也看到了,除了第6个是我自己加的以外,其他的都是我们在使用express -e TodoList这个express模板的使用express所需要的。我们我们只是需要添加这个mongoose模块就好了cnpm install mongoose --save。如果上面的添加mongoose模块中的cnpm--save你还不知道是什么意思,建议你去google一下喽.

第二步

从上面我们可以看到,我们使用的是ejs模板。但是在使用ejs的时候,我很不习惯加上ejs这个后缀,我知道不止我一个人有这样的爱好:)。所以这里我们开始将ejs转换为html的后缀使用。方法大家可以去Google一下,这里贴出了:

    var ejs = require('ejs');    app.engine('html', ejs.__express);    app.set('view engine', 'html');

修改app.js文件中的相关代码就可以了:) 然后,就是确定我们需要用到几个html页面了。其实就是上面的网址我们看到的,一个是主页面,还有一个是历史查看页面。这两个页面的差别真的不大啦,其实是可以用一个页面来完成的,但是这里我用的两个页面用一个页面会更方便,我这里当时没有想到。然后就是我们需要一个前端的框架,那就是前文提到的Amaze,还不会使用的小伙伴们可以去官网使用一下,很简单的,用一下就会了。上面的assets文件夹里面的就是Amaze所必须的相关文件,我们放到public文件夹就好了,这个静态文件目录我们是可以直接读取到的。 之后我们就可以在html页面使用前端的框架了。 
index.html文件代码如下:

<!doctype html>  <html class="no-js">  <head>    <meta charset="utf-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="description" content="">  <meta name="keywords" content="">  <meta name="viewport"        content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">  <title>随时记事</title>  <!-- Set render engine for 360 browser -->  <meta name="renderer" content="webkit">  <!-- No Baidu Siteapp-->  <meta http-equiv="Cache-Control" content="no-siteapp"/>  <link rel="icon" type="image/png" href="assets/i/favicon.png">  <!-- Add to homescreen for Chrome on Android -->  <meta name="mobile-web-app-capable" content="yes">  <link rel="icon" sizes="192x192" href="assets/i/app-icon72x72@2x.png">  <!-- Add to homescreen for Safari on iOS -->  <meta name="apple-mobile-web-app-capable" content="yes">  <meta name="apple-mobile-web-app-status-bar-style" content="black">  <meta name="apple-mobile-web-app-title" content="Amaze UI"/>  <link rel="apple-touch-icon-precomposed" href="assets/i/app-icon72x72@2x.png">  <!-- Tile icon for Win8 (144x144 + tile color) -->  <meta name="msapplication-TileImage" content="assets/i/app-icon72x72@2x.png">  <meta name="msapplication-TileColor" content="#0e90d2">  <link rel="stylesheet" href="assets/css/amazeui.min.css">  <link rel="stylesheet" href="assets/css/app.css"></head>  <body><header data-am-widget="header" class="am-header am-header-default">    <h1 class="am-header-title">    <a href="#title-link" class="">For Adron</a>  </h1></header><!--在这里编写你的代码-->  <ul id="contentUl" class="am-list am-list-static am-list-border am-list-striped">      <% allContent.forEach(function(todo, index){ %>    <li ><%= todo.content %> <button onclick="deleteContent('<%= todo.id %>', this)" style="float:right;" type="button" class="am-close">&times;</button></li>    <% }) %></ul>  <div class="am-u-lg-6">    <div class="am-input-group">    <input id="content" type="text" class="am-form-field">    <span class="am-input-group-btn">      <button class="am-btn am-btn-default" type="button" onclick="addContent()">添加</button>    </span>  </div></div><script>      var xmlhttp;    if (window.XMLHttpRequest)      {// code for IE7+, Firefox, Chrome, Opera, Safari        xmlhttp=new XMLHttpRequest();      }    else      {// code for IE6, IE5        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");      }    function addContent() {//        var content = document.getElementById("content").value;        var content = $("#content").val();        xmlhttp.open("GET","/add?content="+content,false);        xmlhttp.send();        if (xmlhttp.status == 200) {            var contentUl=document.getElementById('contentUl');            var li = document.createElement("li");            var id = "'" + xmlhttp.responseText + "'";            var onclickStr = '<button onclick="deleteContent(' + id + ', this)" style="float:right;" type="button" class="am-close">&times;</button>'            li.innerHTML = content + onclickStr;            contentUl.insertBefore(li,contentUl.childNodes[0]);        $("#content").val("");        }    }    function deleteContent(id, obj) {        $(obj).parent().remove();        xmlhttp.open("GET","/delete?id="+id,true);        xmlhttp.send();        if (xmlhttp.status == 200) {        }    }</script><!--[if (gte IE 9)|!(IE)]><!-->  <script src="assets/js/jquery.min.js"></script>  <script src="assets/js/amazeui.min.js"></script>  <!--<![endif]-->  <!--[if lte IE 8 ]>  <script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>  <![endif]-->  </body>  </html>  

大家可以先看开头和结尾,使用了css和js的部分,其他的后面会说:)

对数据库的增删读改操作

对数据库的操作文件如下图:我们mkdir models文件夹 首先,我们建立一个对数据库的文件配置操作:mongodb.js

var mongoose = require('mongoose');  mongoose.connect('mongodb://127.0.0.1/MorePersonTodo');  exports.mongoose = mongoose;  

这里我们配置了数据库的名称MorePersonTodo。当然,对如何使用mongoose还不熟悉的朋友们,建议Google一下相关的使用方法。 
Todo.js文件就是具体的操作了,代码如下:

[yangfan-23:37-~/TodoForMorePerson/models-49]cat Todo.jsvar mongodb = require('./mongodb.js');  var Schema = mongodb.mongoose.Schema;  var TodoSchema = new Schema({      content: String,    show: Boolean});var TodoModel = mongodb.mongoose.model("Todo", TodoSchema);function Todo(content, show) {    this.content = content;  this.show = show;};Todo.prototype.save = function(todo, callback) {    var todo = {      content: todo.content,      show: todo.show  };  var newTodo = new TodoModel(todo);  newTodo.save(function (err, todo) {    if (err) {      return callback(err);    }    callback(null, todo);  });};Todo.prototype.get = function(callback) {    TodoModel.find({'show':true}, function (err, todos) {    if (err) {      return callback(err);    }    callback(null, todos);  });};Todo.prototype.getAll = function(callback) {    TodoModel.find(function (err, todos) {    if (err) {      return callback(err);    }    callback(null, todos);  });};Todo.prototype.delete = function(id, callback) {      TodoModel.update({'_id':id}, {'show':false}, function(err) {      if (err) {        return callback(err);      }      callback(null);    });};module.exports = Todo;  

详细说明如下: 首先我们建立了一个Schema和Model

var mongodb = require('./mongodb.js');  var Schema = mongodb.mongoose.Schema;  var TodoSchema = new Schema({      content: String,    show: Boolean});var TodoModel = mongodb.mongoose.model("Todo", TodoSchema);function Todo(content, show) {    this.content = content;  this.show = show;};

然后是写入操作:

Todo.prototype.save = function(todo, callback) {    var todo = {      content: todo.content,      show: todo.show  };  var newTodo = new TodoModel(todo);  newTodo.save(function (err, todo) {    if (err) {      return callback(err);    }    callback(null, todo);  });};

然后是查询操作:

Todo.prototype.get = function(callback) {    TodoModel.find({'show':true}, function (err, todos) {    if (err) {      return callback(err);    }    callback(null, todos);  });};

注意这里我们添加了查询条件是{'show':true}我们查询的是标志位true的记录。 
然后是得到所有操作,这里我们可以看到历史记录:

Todo.prototype.getAll = function(callback) {    TodoModel.find(function (err, todos) {    if (err) {      return callback(err);    }    callback(null, todos);  });};

然后就是我们的删除记录操作,当然我们是修改show的参数,而不是真的删除:

Todo.prototype.delete = function(id, callback) {      TodoModel.update({'_id':id}, {'show':false}, function(err) {      if (err) {        return callback(err);      }      callback(null);    });};

最后,我们把整个Todo导出供其他js文件调用:

module.exports = Todo;  

这样,我们的对数据库的操作就完成了:)

路由转发

下面,我们就开始对我们在不同操作下,路由的转发以对数据库进行不同条件下的操作了。 
我们的代码在routes/index.js文件中:

[yangfan-23:46-~/TodoForMorePerson/routes-55]cat index.jsvar express = require('express');  var Todo = require("../models/Todo.js");  var router = express.Router();/* GET home page. */router.get('/', function(req, res) {    var todo = new Todo();  todo.get(function(err, todoBack){    res.render('index', { allContent: todoBack.reverse() });  });});router.get('/add', function(req, res) {    var content = req.query.content;  var todo = new Todo(content, true);  todo.save(todo, function(err, todoBack){    if (err) {        res.writeHead(500);    } else {        res.writeHead(200);    }    res.write(todoBack.id);    res.end();  });});router.get('/delete', function(req, res) {      var id = req.query.id;    var todo = new Todo();    todo.delete(id, function(err){      if (err) {          res.writeHead(500);      } else {          res.writeHead(200);      }      res.end();    });});router.get('/all', function(req, res) {    var todo = new Todo();  todo.getAll(function(err, todoBack){    res.render('all', { allContent: todoBack.reverse() });  });});module.exports = router;  

这里我就不详细说明了,我想大家看到代码的意思就是懂得了:)

Ajax的使用

我们知道,Ajax是划时代的产物,通过javascript实现这个不刷新网页就可以更新页面的技术真的很好。 
1.获取到我们需要的待办事项到我们的主页面中: 
index.js:

/* GET home page. */router.get('/', function(req, res) {    var todo = new Todo();  todo.get(function(err, todoBack){    res.render('index', { allContent: todoBack.reverse() });  });});

index.html:

<ul id="contentUl" class="am-list am-list-static am-list-border am-list-striped">      <% allContent.forEach(function(todo, index){ %>    <li ><%= todo.content %> <button onclick="deleteContent('<%= todo.id %>', this)" style="float:right;" type="button" class="am-close">&times;</button></li>    <% }) %></ul>  

这样我们就将所有的结果输出到页面了。大家可能注意到<button>xxx</button>这个位置的代码了,我们下面会说。 
2.增加我们的待办事项 
index.js:

router.get('/add', function(req, res) {    var content = req.query.content;  var todo = new Todo(content, true);  todo.save(todo, function(err, todoBack){    if (err) {        res.writeHead(500);    } else {        res.writeHead(200);    }    res.write(todoBack.id);    res.end();  });});

index.html:

<script>      var xmlhttp;    if (window.XMLHttpRequest)      {// code for IE7+, Firefox, Chrome, Opera, Safari        xmlhttp=new XMLHttpRequest();      }    else      {// code for IE6, IE5        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");      }    function addContent() {//        var content = document.getElementById("content").value;        var content = $("#content").val();        xmlhttp.open("GET","/add?content="+content,false);        xmlhttp.send();        if (xmlhttp.status == 200) {            var contentUl=document.getElementById('contentUl');            var li = document.createElement("li");            var id = "'" + xmlhttp.responseText + "'";            var onclickStr = '<button onclick="deleteContent(' + id + ', this)" style="float:right;" type="button" class="am-close">&times;</button>'            li.innerHTML = content + onclickStr;            contentUl.insertBefore(li,contentUl.childNodes[0]);        $("#content").val("");        }    }    function deleteContent(id, obj) {        $(obj).parent().remove();        xmlhttp.open("GET","/delete?id="+id,true);        xmlhttp.send();        if (xmlhttp.status == 200) {        }    }</script>  

我们使用了Ajax。当我们点击“添加”按钮的使用,就触发了javascript中“addContent”函数。这里不对如何使用Ajax进行介绍,如果您还不会,还是Google的说。这里需要注意的是,如果我们添加成功的话,会返回200,这时我们已经获取到添加事项在数据库中的唯一id。我们把这个id放在button中,是为了在删除这个事项的时候唯一确定该事项使用的。 
然后,我们通过javascript代码:

var contentUl=document.getElementById('contentUl');              var li = document.createElement("li");            var id = "'" + xmlhttp.responseText + "'";            var onclickStr = '<button onclick="deleteContent(' + id + ', this)" style="float:right;" type="button" class="am-close">&times;</button>'            li.innerHTML = content + onclickStr;            contentUl.insertBefore(li,contentUl.childNodes[0]);

把这条记录放置在li列表的第一个位置:) 
3.删除一条事项记录 
index.js:

router.get('/delete', function(req, res) {      var id = req.query.id;    var todo = new Todo();    todo.delete(id, function(err){      if (err) {          res.writeHead(500);      } else {          res.writeHead(200);      }      res.end();    });});

index.html:

    function deleteContent(id, obj) {        $(obj).parent().remove();        xmlhttp.open("GET","/delete?id="+id,true);        xmlhttp.send();        if (xmlhttp.status == 200) {        }    }

我们还是使用Ajax,我们为了速度,是先把这条已经已经li删除了$(obj).parent().remove();:),然后开始执行数据库操作。注意我们删除只是把show参数变为false以不在读取,不是真的删除。 
4.读取所有历史记录: 
index.js

router.get('/all', function(req, res) {    var todo = new Todo();  todo.getAll(function(err, todoBack){    res.render('all', { allContent: todoBack.reverse() });  });});

我们访问xxxx/all就可以看到所有的历史记录了:) 代码下载地址:https://github.com/yangfanacc/Todo 这里谢谢大家给个星星(Star)哦 :)

1 0
原创粉丝点击