美文网首页Node学习之路
Node.js学习第七天笔记之登录注册项目和留言板项目

Node.js学习第七天笔记之登录注册项目和留言板项目

作者: 果木山 | 来源:发表于2018-12-17 12:38 被阅读0次

    1 登录注册项目(form请求)

    • 项目文件:

      • MVC:
        • models:创建db.js,用于引入封装的数据库方法;创建md5.js,用于引入加密函数,对密码加密;
        • views:创建login.ejs和reg.ejs文件,用于呈现登录和注册页面;
        • controllers:管理者,创建router.js,作为管理器;
      • mongodb:数据库;
      • form-app.js:服务器;
      • setting.js:作为db.js中引入,用于设置数据库地址url和数据库名字dbName;
      • 下载模块:express ejs mongodb formidable express-session
      • package.json:用于记录信息;
    • 思路:

      • 服务器中设置请求:
        • get:"/login" => 用于渲染页面login.ejs;
        • post:"/dologin" => 用于提交登录数据;
        • get:"/reg" => 用于渲染页面reg.ejs;
        • post:"/doreg" => 用于提交注册数据;
      • 渲染页面:res.render();
      • 获取表单post提交的数据:formidable;
      • 对密码进行加密处理;crypto md5;
      • 通过db.js中封装的数据库方法;对数据进行查找和插入;
        • db.find():用于查找数据;
        • db.insertOne():用于插入数据;
      • 登录成功和注册成功时,均需要设置session;
    • 知识点:

      • md5加密
        • 模块:node.js中的系统模块crypto;如:const crypto=require("crypto");
        • 创建md5格式的hash;如:const hash=crypto.createHash("md5");
        • 更新和转化数据str;必须为字符串;
          • 代码:var res=hash.update(str).digest("base64")
          • res为32为的乱码字符串;
          • 可进行重复加密,不易解密;如password=crypto.md5(crypto.md5(password)+"guomushan");
        • md5封装函数代码:
         exports.md5=function(str){
             //引入node系统模块
             const crypto=require("crypto");
             //创建hash
             const hash=crypto.createHash("md5");//创建md5格式;
             //加密文件
             return hash.update(str).digest("base64");//加密成64为的字符串;
         };
        
      • get请求用来渲染页面,post请求用来提交数据
      • 用formidable模块,获取表单post请求提交的参数;
      • 使用express模块创建服务器;
      • 使用express-session模块设置session;
        • 注意:引入中间件;获取和设置均用req;
      • 使用ejs模板渲染页面;需要设置模板引擎;
      • 数据库方法的封装中需要通过settings设置url和dbName;
    • 实例代码

      • 服务器form-app.js代码:
       //引入node系统模块
       
       //引入第三方模块
       const express=require("express");
       const session=require("express-session");
       
       //引入自定义模块
       const router=require("./controller");
       
       //创建服务器
       const app=express();
       //设置模板引擎
       app.set("view engine","ejs");
       //引入session中间件
       app.use(session({
           secret: 'keyboard cat',
           resave: false,
           saveUninitialized: true,
           cookie: { secure: false }//设置为false;
       }));
       
       //1.发送请求get:"/login" => 渲染登录页面
       app.get("/login",router.showlogin);
       //1.1 发送请求post:"/dologin" => 提交数据
       app.post("/dologin",router.dologin);
       
       //2.发送请求get:"/reg" => 渲染注册页面
       app.get("/reg",router.showreg);
       //2.1 发送请求post:"/reg" => 提交数据
       app.post("/doreg",router.doreg);
       
       //监听
       app.listen(8080);
      
      • 管理器router.js代码:
       //引入第三方模块
       const formidable=require("formidable");
       
       //引入自定义模块
       const db=require("../models/db");
       const crypto=require("../models/md5");
       
       //导出
       //渲染登录页面;
       exports.showlogin=function (req, res, next) {
           res.render("login");
       };
       //提交登录数据
       exports.dologin=function (req, res, next){
           const form=new formidable.IncomingForm();
           form.parse(req,function (err, fields, files) {
               var username=fields.username;
               var password=fields.password;//在页面中拿到的数据都是字符串;
               //密码加密处理
               password=crypto.md5(crypto.md5(password)+"guomushan");//双重加密
               db.find("users",{username},function (err, result) {
                   if(err){
                       res.send("服务器错误");
                       return;
                   }
                   if(result.length){
                       if(result[0].password===password){
                           //设置session
                           req.session.login="true";
                           req.session.username=username;
                           //登录成功
                           res.send({"bok":true,"msg":"恭喜你,登录成功!!!"})
                       }else{
                           res.send({"bok":false,"msg":"密码不正确,请重新输入"});
                       }
                   }else{
                       res.send({"bok":false,"msg":"用户名不存在,请注册!!!"});
                   }
               })
           })
       };
       
       //渲染注册页面
       exports.showreg=function (req, res, next) {
           res.render("reg");
       };
       //提交注册数据
       exports.doreg=function (req, res, next) {
           //通过formidable模块获取数据
           const form=new formidable.IncomingForm();
           form.parse(req,function (err, fields, files) {
               if(err){
                   res.send("获取数据失败");
                   return;
               }
               //拿到数据后需要对密码加密
               var username=fields.username;
               var password=fields.password;//在页面中拿到的数据都是字符串;
               //密码加密处理
               password=crypto.md5(crypto.md5(password)+"guomushan");//双重加密
               //连接数据库,查找数据,若无,则插入数据
               db.find("users",{username},function (err, result) {
                   if(err){
                       res.send("服务器错误");
                       return;
                   }
                   if(result.length){
                       //长度不为0,则代表数据存在;
                       res.send({"bok":false,"msg":"注册失败,该用户名已被注册!!!"});
                       return;
                   }else{
                       //长度为0,就证明用户名不存在,插入数据到数据库中;
                       db.insertOne("users",{username,password},function (err, result) {
                           if(err){
                               res.send("服务器错误");
                               return;
                           }
                           //设置session
                           req.session.login="true";
                           req.session.username=username;
                           //注册成功
                           res.send({"bok":true,"msg":"注册成功,请登录!!!"});
                       })
                   }
               })
           })
       };
      
      • 页面login.ejs代码:
       <!doctype html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <title>登录页面</title>
           <style>
               div{
                   width:500px;
                   height: 200px;
                   padding-top: 10px;
                   margin: 150px auto;
                   text-align: center;
                   background-color: lightpink;
               }
           </style>
       </head>
       <body>
       <div>
           <h1 style="color:blue;">登录页面</h1>
           <form action="/dologin" method="post">
               <p>
                   <label for="user">
                       用户名:<input type="text" id="user" name="username"/>
                   </label>
               </p>
               <p>
                   <label for="pass">
                       密  码:<input type="password" id="pass" name="password"/>
                   </label>
               </p>
               <input type="submit" value="请登录"/>
           </form>
       </div>
       </body>
       </html>
      

    2 登录注册项目(ajax请求)

    • 请求方式使用ajax请求配合表单
      • ajax请求中主要是需要获取表单中的键值对,通过$("form").serialize();表单序列化拿到{key:val,key:val}格式的数据;与form的action以及method均无关;
      • 与form表单的区别:将submit按钮去掉,换成input(button)按钮,给其添加点击事件;然后触发事件,发送ajax请求;
      • 注意:不能换成<button>按钮,其点击后会默认提交get请求,会出错;
      • 先决条件:必须引入jQuery.js文件,所以需要设置静态资源目录,然后利用相对路径引入js文件;
    • login-ajax.ejs文件
      • form表单用于提供键值对数据,通过$("form").serialize()表单序列化来拿到键值对参数;
      • 设置按钮<input type="button" id="btn" value="请登录"/>;添加点击事件,进行ajax请求;
      • 引入jQuery.js文件;
      • 代码:
       <!doctype html>
       <html lang="en">
       <head>
           <meta charset="UTF-8">
           <title>登录页面</title>
           <style>
               div{
                   width:500px;
                   height: 200px;
                   padding-top: 10px;
                   margin: 150px auto;
                   text-align: center;
                   background-color: lightpink;
               }
           </style>
       </head>
       <body>
       <div>
           <h1 style="color:blue;">登录页面</h1>
           <form>
               <p>
                   <label for="user">
                       用户名:<input type="text" id="user" name="username"/>
                   </label>
               </p>
               <p>
                   <label for="pass">
                       密  码:<input type="password" id="pass" name="password"/>
                   </label>
               </p>
               <input type="button" id="btn" value="请登录"/>
           </form>
       </div>
       <script src="/js/jquery.js"></script>
       <script>
           $("#btn").on("click",function () {
               $.ajax({
                   url:"/dologin",
                   type:"post",
                   data:$("form").serialize(),
                   dataType:"json",
                   success:function (val) {
                       alert(val.msg)
                   }
               })
           })
       </script>
       </body>
       </html>
      
    • ajax-app.js服务器文件
      • 与form-app.js的区别在于,设置静态资源目录,用于引入jQuery.js文件;
      • 在渲染页面时,渲染login-ajax.ejs和reg-ajax.ejs文件;
      • 静态资源设置代码:app.use(express.static("./public"))

    3 知识点:form表单submit提交按钮发送请求与ajax发送请求

    3.1 form表单和ajax发送get请求

    • form表单和ajax提交get请求中如何设置数据参数;
      • form表单中get请求和post请求,区别就在于method设置不同,其余的设置没有区别,设置参数,都是通过name和value值;
      • form表单提交get请求;会默认将参数用问号拼接在url后面,显示在地址栏中;
    • ajax发送get请求如何设置数据参数;
      • ajax发送get请求时,type属性设置为"get",参数以键值对(key=val&key=val)的形式通过问号拼接在域名地址后面;设置url属性中;
      • 代码:
       //点击span发送post请求;
       $("span").click(function () {
           $.ajax({
               url:"/test?meiaho=djfj&tiankong=djid",
               type:"get",
               success:function (val) {
                   alert(val);
               }
           })
       })
      
    • 获取form表单submit提交按钮发送请求与ajax发送请求的参数
      • 在express中用req.query获取参数,为一个对象;

    3.2 form表单和ajax发送post请求

    • 注意:
      • ajax设置data属性可以是key=val&key=val键值对;也可以是:{key:val,key:val}对象;
      • ajax中发送get请求和post请求,都可以设置data属性;
    • form表单和ajax提交post请求中如何设置数据参数;
      • form表单中设置post请求提交的参数:在每个文本框中设置name值和value值;通过submit提交自动形成{key:val,key:val}对象形式;参数不会呈现在地址栏中;
      • ajax设置post请求提交的参数:设置data属性,属性值格式为:{key:val,key:val}对象
    • form表单submit提交按钮-发送post请求
      • 表单结构:
        • form标签中设置action,method,enctype
          • action:指的是上传的服务器地址,包括完整的路由,如:http://localhost:8080/dologin;当地址栏中已经是在http://localhost:8080环境下,此时就只写/dologin即可;
          • method:指的是请求样式,一般为get和post请求;
          • ectype:指的是在post请求中根据上传数据的大小来设置;
            • 小数据:application/x-www-form-urlencoded;为默认值;可以省略;
            • 大数据:multipart/form-data;一般用于file文件上传和textarea文本上传;
        • 在表单input中必须设置name值,此值作为上传格式{key:val,key:val}中的key值;表单中输入的内容作value值;
        • 设置input类型为submit;点击默认提交数据;
      • 重要关键:表单发送请求,必须要设置submit类型,点击可提交请求;其他类型都不行;如何没有它,数据根本不能提交;
      • 代码:
       //action设置的前提条件是在"http://localhost:8080"环境下提交,才能省略;否则必须写全;
       <form action="/dologin" method="post">
           <p>
               <label for="user">
                   用户名:<input type="text" id="user" name="username"/>
               </label>
           </p>
           <p>
               <label for="pass">
                   密 码:<input type="password" id="pass" name="password"/>
               </label>
           </p>
           <input type="submit" value="请登录"/>
       </form>
      
    • ajax提交请求
      • 前提条件:必须引入jQuery.js文件或自己封装的ajax.js文件;能够正常使用ajax;
      • 在项目中使用时,
        • 新建public文件夹,存放静态文件,如js等文件;
        • 在服务器中设置静态资源目录为public目录下,如app.use(express.static("./public"));
        • 在html或ejs文件中,通过script引入jQuery.js文件,src设置相对路径在public目录下,才能引入成功;
      • 设置ajax属性参数;
        • url:指的是上传的服务器地址,包括完整的路由,如:http://localhost:8080/dologin;当地址栏中已经是在http://localhost:8080环境下,此时就只写/dologin即可;与form表单中的action设置等同;
        • type:设置"post",指post请求;
        • data:设置参数,格式为{key:val,key:val}
        • dataType:设置接收数据的类型,一般为json格式;
        • success:匿名函数接收服务器中res.send()或res.end()响应回来的数据;
      • 代码:
        • login1.ejs文件代码:
         <!doctype html>
         <html lang="en">
         <head>
             <meta charset="UTF-8">
             <title>ajax发送post请求</title>
         </head>
         <body>
         <div>
             <span style="background-color: red;cursor:pointer">提交</span>
         </div>
         <script src="/js/jquery.js"></script>
         <script>
             //点击span发送post请求;
             $("span").click(function () {
                 $.ajax({
                     url:"/href",
                     type:"post",
                     data:{meiaho:djfj,tiankong:djid},
                     success:function (val) {
                         alert(val);
                     }
                 })
             })
         </script>
         </body>
         </html>
        
        • 服务器代码:
         //设置静态资源目录,用于引用css或js文件;
         app.use(express.static("./public"));
         
         //设置get请求"/main",渲染login1.ejs页面
         app.get("/main",function (req, res) {
             res.render("login1");
         });
         //发送post请求"/href",提交数据,此地址为ajax中url属性设置;
         app.post("/href",function (req, res) {
             const formidable=require("formidable");
             const form=new formidable.IncomingForm();
             form.parse(req,function (err, fields, files) {
                 if (err) {
                     res.send("获取数据失败");
                     return;
                 }
                 console.log(fields);
                 res.send("111");//success接收的数据111
             })
         });
        
    • 获取form表单submit提交按钮发送请求与ajax发送请求的参数
      • 使用formidable模块获取post请求提交的参数;
        • 引入模块const formidable=require("formidable");
        • 新建form对象 const form=new formidable.IncomingForm();
        • 利用form.parse(req,function(err,fields,files){})中的fields获取数据,为一个对象;
      • 总结:不管通过什么形式发送post请求,formidable都能获取到发送请求中的参数;

    4 留言板项目

    • 项目效果:
      • 通过地址栏输入地址,来获取留言页面;数据更新显示
      • 输入留言内容,点击提交按钮后,页面刷新,数据更新;
      • 刚刚提交的数据在第一页显示;
      • 页面进行分页显示;默认第一页显示;
      • 点击页面删除按钮,数据删除,页面更新;
    • 思路:
      • get:"/liuyan" => 渲染页面,展现留言面板;
      • post:"/doliuyan" => 提交数据,利用ajax提交,提交成功后需要刷新页面,所以不能使用表单提交;
      • 页面在渲染打开后,直接发送get请求,向数据库获取数据;
        • get: "/getliuyan" => 向数据库获取数据,通过DOM操作插入到页面中;
      • 所有数据都显示在页面中;
      • 实现排序和分页;
        • 在获取数据时,传入实参sort,来控制降序还是升序,此时用的是降序,通过time属性排序;
        • 是在获取数据时,传入实参page和pageamount,来设置分页;
          • 在第三步发送get请求"/getliuyan"时,需要给ajax设置data属性,传入page和pageamount属性;来获取分页数据;
      • 所以需要在获取数据之前先获取数据的总个数,然后计算出page页码个数;在拿数据,pageamount设置定值就好;
      • 设置ajax请求,get:"/getcount" => 获取所有数据的总个数;通过计算得到page页码个数;
        • 根据页码个数,插入DOM中,显示页码;
      • 页面加载后,默认在第一页显示,显示第一页的数据;所以需要设置page为0;$Li中第一个添加active类名;
      • 页码与数据进行同步设置
        • 给每个页码添加点击事件;然后拿到页码的索引值;
        • 设置点击谁,给谁添加active类名,将其点亮,其他的兄弟元素删除active类型;
        • 通过索引值来设置page值,进而再次请求数据,拿到数据,插入DOM;所以需要将获取数据的ajax封装在一个函数中;然后调用函数,传入实参,为索引值;
      • 点击页面上的删除按钮,删除数据,重新刷新页面;
        • 通过数据库中每条数据中的唯一的"_id"值,来进行查找;
        • 发送请求:通过a标签中的href来发送get请求,请求的地址为"/delete/id值";
        • 在服务器中通过设置get请求地址为正则表达式的地址"/delete/:xx";这样id的值为任意值,通过req.params.xx就能拿到请求时的id值;
        • 在数据库中数据为一个对象,对象中的属性为"_id",属性值为:ObjectId("5c16fef27b4f0c2374efd5ae");所以在调用deleteMany方法时,设置的json格式也为此格式;
        • 所以需要用到mongdb中的模块ObjectID,则需要引入模块;即const ObjectID = require('mongodb').ObjectID;
        • 查找数据时的json为:{"_id":ObjectID(id)};
        • 在删除数据成功后,需要跳转到原来页面,也就是再发送一次"/liuyan"的请求;用到的知识点为:res.redirect("/liuyan");;即,跳转到某页面;
        • 如果想要对删除成功后做出响应,可以使用ajax请求;通过success函数内操作;
    • 注意:
      • 重点:
        • 在此项目中需要用到jQuery.js和bootstrap.js等文件;需要在页面中引用;所以必须设置静态资源目录;
        • 引入css和js文件时,在静态资源目录相对路径下设置;
      • 此项目中,指对页面进行了三次刷新;
        • 第一次:地址栏输入"/liuyan";打开留言页面;
        • 第二次:提交数据完成后,前端刷新页面;用到的代码:window.location.href="/liuyan";
        • 第三次:在删除数据后,服务器端通过res.redirect()跳转页面;即再次发送请求;代码:res.redirect("/liuyan");
        • 注意:在页面刷新后,就会默认设置第一页数据显示,所以在分页点击时,不能刷新页面;必须重新调用findData函数,获取数据,重新插入DOM;
      • 此项目均使用ajax提交请求,不用表单的原因:ajax提交请求,可以通过success拿到响应结果,对其进行操作,而表单不能对响应结果进行操作;
      • 项目中ajax请求默认是异步操作的,所以想让其同步运行,必须设置async属性为false;
      • 项目中ajax请求的两种形式都使用了;
        • post请求提交数据,get获取数据;
        • 二者的参数都是通过data属性进行设置,一般设置为对象,也可以是键值对格式的字符串;
        • ajax请求中,get请求提交的参数,在服务器端通过req.query来拿,拿到一个对象;
        • ajax请求中,post请求提交的参数,在服务器端通过formidable模块来拿;拿到的也是一个对象;
      • 此项目中,从数据库中获取数据,封装为一个函数;总共调用了两次
        • 第一次:默认设置页面为第一页,显示第一页的数据,调用findData()函数,传入实参为0;即设置page值为0;进而获取第一页的数据;
        • 第二次:分页设置点击事件中,当点击某一页时,获取此元素的索引,作为调用findData()函数的实参,即设置page的值,从而拿到对应页码的数据,然后插入DOM显示;
      • 时间的设置,通过第三方模块silly-datetime,设置成固定格式,然后插入到数据库;
    • 代码:
      • levmes.ejs文件代码:
       <!DOCTYPE html>
       <html lang="zh-CN">
       <head>
           <meta charset="utf-8">
           <title>留言板</title>
           <link href="/css/bootstrap.css" rel="stylesheet">
           <style>
               body{
                   font-size: 18px;
               }
               @media (min-width: 768px){
                   .form-horizontal .control-label{
                       padding-top: 0;
                   }
               }
           </style>
       </head>
       <body>
       <div class="container">
           <h1 style="text-align: center;padding:20px;">我的留言板</h1>
           <form class="form-horizontal" style="width: 50%;margin:0 auto;">
               <div class="form-group">
                   <label for="user" class="col-md-2 control-label">姓 名</label>
                   <div class="col-md-10">
                       <input type="text" class="form-control" id="user" name="username" placeholder="请输入姓名">
                   </div>
               </div>
               <div class="form-group">
                   <label for="contents" class="col-md-2 control-label">留 言</label>
                   <div class="col-md-10">
                       <textarea class="form-control" name="contents" id="contents" cols="20" rows="5" placeholder="请输入留言"></textarea>
                   </div>
               </div>
               <div class="form-group">
                   <div class="col-sm-offset-2 col-sm-10">
                       <input type="button" class="btn btn-default" id="btn" value="请提交">
                   </div>
               </div>
           </form>
       </div>
       <div class="container">
           <nav aria-label="Page navigation" style="width: 50%;margin:10px auto 0; font-size:14px;padding-left: 30px;">
               <ul class="pagination" id="ul2">
                   <!--<li><a href="#">1</a></li>-->
               </ul>
           </nav>
           <ul class="list-group" id="ull" style="width: 50%;margin:10px auto 0; font-size:14px; padding-left: 30px;">
               <!--<li class="list-group-item">
                   <p>【姓名】:xxx</p>
                   <p>【留言】:xxx</p>
                   <p>【事件】:xxx</p>
                   <p><a href="">删除</a></p>
               </li>-->
           </ul>
       </div>
       <script src="/js/jquery.js"></script>
       <script src="/js/bootstrap.js"></script>
       <script>
           var $user=$("#user"),
               $contents=$("#contents"),
               $time=new Date(),
               pageamount=3;
       
           //1. ajax发送post请求,提交表单数据
           $("#btn").on("click",function () {
               $.ajax({
                   url:"/doliuyan",
                   type:"post",
                   data:{username:$user.val(),contents:$contents.val()},//时间通过后台传入
                   success:function (val) {
                       if(val.bok){
                           //alert(val.msg);
                           window.location.href="/liuyan";//数据提交成功后,重新刷新页面;
                       }else{
                           console.log(val.msg);
                       }
                   }
               })
           })
           //2. get请求,获取数据库中的数据总个数,算出页码个数,插入DOM
           $.ajax({
               url:"/getcount",
               type:"get",
               async:false,//必须设置为同步
               success:function (val) {
                   if(val.bok){
                       //获取到总个数,计算分页的个数page
                       var countAll=val.msg;
                       var pageAll=Math.ceil(countAll/pageamount);//向上取整
                       //确定页码的个数,然后插入DOM
                       var str="";
                       for(var i=0; i<pageAll; i++){
                           str+=`<li><span style="cursor:pointer">${i+1}</span></li>`;
                       }
                       $("#ul2").html(str);
                   }else{
                       console.log(val.msg);
                   }
               }
           })
       
           //3. 插入DOM后,获取元素li,默认设置第一个页码点亮,并显示第一页数据;注意:jQuery中无DOM映射;
           var $aLi=$("#ul2").children("li");
           //默认让第一页显示;并显示第一页的数据
           $($aLi[0]).addClass("active");
           findData(0);//默认获取第一页数据;
       
           //4.每个li添加点击事件,然后点亮它,点击事件触发后,不能请求页面;否则会默认为第一页;
           $aLi.click(function () {
               //获取页码索引
               var n=$(this).index();
               $(this).addClass("active").siblings("li").removeClass("active");
               //设置同步数据
               findData(n);//设置page值,拿到对应的数据,插入页面;
           })
       
           //封装方法findData:ajax发送get请求,拿数据,放入DOM,只要页面一加载,立刻发送请求,拿数据;
           function findData(index) {
               $.ajax({
                   url:"/getliuyan",
                   type:"get",
                   data:{page:index,pageamount},//分页传参
                   async:false,
                   success:function (val) {
                       if(val.bok){
                           //拿到数据库数据,将其插入到DOM中;
                           var str="";
                           $.each(val.msg,function () {
                               str+=`<li class="list-group-item"><p>【姓名】:${this.username}</p><p>【留言】:${this.contents}</p><p>【时间】:${this.time}</p><p><a href="/delete/${this._id}">删除</a></p></li>`})
                           //插入到DOM
                           $("#ull").html(str);
                       }else{
                           console.log(val.msg);
                       }
                   }
               })
           }
       
           //5.点击页面删除按钮,数据删除,页面更新;
           //此处利用a标签href提交get请求;
           //如果想要对删除成功后做出响应,可以使用ajax请求;通过success函数内操作;
       </script>
       </body>
       </html>
      
      • levmes-app.js服务器代码:
       const express=require("express");
       const router=require("./controller/router2");
       const app=express();
       app.listen(8080);
       
       //设置模板引擎
       app.set("view engine","ejs");
       //设置静态资源目录
       app.use(express.static("./public"));
       
       //1.渲染页面
       app.get("/liuyan",router.showIndex);
       //2.post提交数据,ajax请求的数据
       app.post("/doliuyan",router.doliuyan);
       //3.get请求,拿到数据库中的数据,ajax发送get请求
       app.get("/getliuyan",router.getliuyan);
       //4.get请求,拿到数据库中的数据总个数,ajax发送get请求;
       app.get("/getcount",router.getcount);
       //5.get请求,删除数据,更新页面,a标签中href提交的get请求;
       app.get("/delete/:id",router.deleteData);
      
      • router2.js管理器代码:
       //引入模块
       const db=require("../models/db");
       const formidable=require("formidable");
       const ObjectID = require('mongodb').ObjectID;
       const sd = require('silly-datetime');
       
       //导出
       //渲染留言板页面
       exports.showIndex=function (req, res, next) {
           res.render("levmes");
       };
       //提交数据到数据库
       exports.doliuyan=function (req, res, next) {
           //拿到前端ajax提交过来的数据;
           var form=new formidable.IncomingForm();
           form.parse(req,function (err, fields, files) {
               //插入时间数据
               fields.time=sd.format(new Date(),"YYYY-MM-DD HH:mm:ss");
               db.insertOne("liuyan",fields,function (err, result) {
                   if(err){
                       res.send({"bok":false,"msg":"提交数据失败"});
                       return;
                   }
                   res.send({"bok":true,"msg":"留言成功!!!"})
               })
           })
       };
       //获取数据库中数据,响应会前端
       exports.getliuyan=function (req, res, next) {
           //获取前端传来的参数
           var page=req.query.page;
           var pageamount=req.query.pageamount;
           //向数据库获取数据find
           db.find("liuyan",{},{"sort":{"time":-1},page,pageamount},function (err, result) {
               if(err){
                   res.send({"bok":false,"msg":"获取数据库数据失败"});
                   return;
               }
               res.send({"bok":true,"msg":result});
           })
       };
       //获取数据库中的总个数
       exports.getcount=function (req, res, next) {
           db.count("liuyan",{},function (err, result) {
               if(err){
                   res.send({"bok":false,"msg":"获取数据库数据总个数失败"});
                   return;
               }
               res.send({"bok":true,"msg":result});
           })
       };
       //删除数据
       exports.deleteData=function (req, res, next) {
           var id=req.params.id;//通过params拿到冒号后面的数据;
           //拿到数据库每个数据的id值;然后通过ObjectID拼接id处理查找数据;
           db.deleteMany("liuyan",{"_id":ObjectID(id)},function (err, result) {
               if(err){
                   res.send("删除数据失败");
                   return;
               }
               //数据删除成功之后,通过res.redirect()来跳转会原页面;
               res.redirect("/liuyan");
           });
       };
      
      • db.js数据库封装方法代码:
       //引入mongodb模块
       const MongoClient=require("mongodb").MongoClient;
       //引入自定义模块setting
       const setting=require("../setting-liuyan");
       //数据库地址
       const url=setting.url;
       //数据库名
       const dbname=setting.dbName;
       
       //连接数据库
       function mongoConnect(callback) {
           MongoClient.connect(url,{ useNewUrlParser: true },function (err, client) {
               if(err){
                   console.log("连接数据库失败");
                   return;
               }
               //将client通过callback回调函数传出;
               callback(client);
           });
       }
       
       //1.在数据库中指定集合插入一条数据;
       //参数:集合, 插入数据,callback导出信息
       exports.insertOne=function (collectionName, json, callback) {
           mongoConnect(function (client) {
               //获取数据库db,注:3.0以上版本获取数据库会有差异;
               var db=client.db(dbname);
               var col=db.collection(collectionName);
               col.insertOne(json,function (err, result) {
                   callback(err,result);
                   client.close();//关闭与数据库的连接
               })
           })
       };
       
       //2.查找数据库中集合下的数据
       //参数:集合 待查找的数据  分页和排序参数 callback导出信息
       //其中第三个分页和排序参数可传可不传;
       exports.find=function (collectionName,json1,json2,callback) {
           if(arguments.length===3){
               //说明json2没有传;第三个参数传的是回调;
               callback=json2;
               json2={};
           }
           var sort=json2.sort || {};//默认值为空对象,即乱序;
           var limit=Number(json2.pageamount) || 0;//默认值为0,必须为数字
           var skip=Number(json2.page) || 0;//默认跳过0;
           mongoConnect(function (client) {
               var db=client.db(dbname);
               var col=db.collection(collectionName);
               //用toArray将获取的数据以数组的形式传出;
               col.find(json1).sort(sort).limit(limit).skip(skip*limit).toArray(function (err, doc) {
                   callback(err,doc);
                   client.close();//关闭与数据库的链接
               })
           })
       };
       //3 修改更新数据
       //参数:集合 待修改数据  修改后的数据 callback导出信息
       exports.updateMany=function (collectionName, json1, json2, callback) {
           mongoConnect(function (client) {
               var db=client.db(dbname);
               var col=db.collection(collectionName);
               col.updateMany(json1,json2,function (err, result) {
                   callback(err,result);
                   client.close();
               })
           })
       };
       //4 删除
       //参数:集合 待删除 callback导出信息
       exports.deleteMany=function (collectionName, json, callback) {
           mongoConnect(function (client) {
               var db=client.db(dbname);
               var col=db.collection(collectionName);
               col.deleteMany(json,function (err, result) {
                   callback(err,result);
                   client.close();
               })
           })
       };
       //5 获取集合下满足条件的总个数
       //参数:集合 数据 callback导出信息
       exports.count=function (collectionName, json, callback) {
          mongoConnect(function (client) {
              var db=client.db(dbname);
              var col=db.collection(collectionName);
              col.countDocuments(json,function (err, count) {
                  callback(err,count);
                  client.close();
              })
          })
       };
      
      • setting-liuyan.js设置数据库地址和名称文件代码:
       //设置数据库地址
       exports.url="mongodb://localhost:27017";
       //设置数据库名称
       exports.dbName="liuyankuang";
      

    5 留言板项目复习

    • 思路:
      • 通过res.render()来向ejs模板发送参数,前端通过获取的参数渲染DOM页面;
      • 进行分页显示时,可以通过拿到page参数进行跳转设置,get请求:/liuyan?page=2
    • 代码
      • guestbook.ejs代码:
       <!DOCTYPE html>
       <html lang="zh-CN">
       <head>
           <meta charset="utf-8">
           <meta http-equiv="X-UA-Compatible" content="IE=edge">
           <meta name="viewport" content="width=device-width, initial-scale=1">
           <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
           <title>留言板实例</title>
       
           <!-- Bootstrap -->
           <link href="/css/bootstrap.css" rel="stylesheet">
           <link href="/css/guestbook.css" rel="stylesheet">
           <!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
           <!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
           <!--[if lt IE 9]>
           <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
           <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
           <![endif]-->
       </head>
       <body>
       <div class="container">
           <div class="guestcon">
               <h1 style="text-align: center;padding: 20px;">留言板</h1>
               <form class="form-horizontal">
                   <div class="form-group">
                       <label for="user" class="col-sm-2 control-label">姓 名</label>
                       <div class="col-sm-10">
                           <input type="text" class="form-control" name="user" id="user" placeholder="请输入姓名" required>
                       </div>
                   </div>
                   <div class="form-group">
                       <label for="liuyan" class="col-sm-2 control-label">留 言</label>
                       <div class="col-sm-10">
                           <textarea class="form-control" name="msg" id="liuyan" cols="10" rows="5" placeholder="请输入留言" required="required"></textarea>
                       </div>
                   </div>
                   <div class="form-group">
                       <div class="col-sm-offset-2 col-sm-10">
                           <input type="button" id="btn" class="btn btn-primary" value="提交留言"/>
                       </div>
                   </div>
               </form>
               <div class="panelcon">
                   <nav aria-label="Page navigation">
                       <ul class="pagination">
                           <%for(var j=0; j<count; j++){%>
                           <%if(j===page){%>
                           <li class="active"><a href="/liuyan?page=<%= j+1%>"><%= j+1%></a></li>
                           <%}else{%>
                           <li><a href="/liuyan?page=<%= j+1%>"><%= j+1%></a></li>
                           <%}%>
                           <%}%>
                       </ul>
                   </nav>
                   <div class="panel panel-default">
                       <ul class="list-group">
                           <%for(var i=0; i<datas.length; i++){%>
                           <li class="list-group-item">
                               <p>【姓名】:<%= datas[i].username%></p>
                               <p>【留言】:<%= datas[i].msg%></p>
                               <p>【时间】:<%= datas[i].curtime%></p>
                               <p style="text-align: right;margin-bottom: 0;"><a href="/delete/<%= datas[i]._id%>">删除</a></p>
                           </li>
                           <%}%>
                       </ul>
                   </div>
               </div>
           </div>
       </div>
       <script src="/js/jquery.js"></script>
       <script src="/js/bootstrap.js"></script>
       <script>
           //1.按钮点击事件提交数据
           $("#btn").click(function () {
               $.ajax({
                   url:"/doliuyan",
                   type:"post",
                   data:$("form").serialize(),
                   dataType:"json",
                   success:function (val) {
                       if(val.bok){
                           if(val.curr){
                               alert(val.msg);
                               //重新刷新页面
                               window.location.href="/liuyan";
                           }
                       }else{
                           if(val.curr){
                               alert(val.msg);
                           }else{
                               console.log(val.msg);
                           }
                       }
                   },
                   error:function (err) {
                       console.log(err);
                   }
               })
           });
       </script>
       </body>
       </html>
      
      • app.js代码:
       //引入模块
       const express=require("express");
       
       //引入自定义模块
       const router=require("./controllers/router");
       
       //创建服务器
       const app=express();
       
       //设置模板引擎
       app.set("view engine","ejs");
       //设置静态资源目录
       app.use(express.static("./public"));
       //路由设置
       //get:"/liuyan" 渲染留言板页面,并获取指定页码内的数据
       app.get("/liuyan",router.showIndex);
       //post:"/doliuyan" 提交留言数据
       app.post("/doliuyan",router.toLiuyan);
       //get:"/:id" 删除数据
       app.get("/delete/:id",router.deleteData);
       
       
       //端口号监听
       app.listen(5555,function () {
           console.log("5555 server is running");
       });
      
      • router.js代码:
       const formidable=require("formidable");
       const sd=require("silly-datetime");
       const db=require("../models/guestdb");
       const ObjectID=require("mongodb").ObjectID;
       
       module.exports={
           //渲染留言板页面,并获取指定页码内的数据
           showIndex:function (req, res, next) {
               //前端获取参数,如:"/liuyan?page=2"
               var pageobj=req.query;
               //创建page,pageamount
               var page=pageobj.page-1 || 0;
               var pageamount=3;
               //获取所有的数据
               db.find("liuyan",{},{sort:{"curtime":-1},page,pageamount},function (err, docs) {
                   if(err){
                       res.send(err);
                   }
                   //获取所有数据的总个数
                   db.count("liuyan",{},function (err, count) {
                       if(err){
                           res.send(err);
                       }
                       res.render("guestbook",{
                           datas:docs,
                           count:count/pageamount,
                           page:Number(page)
                       });
                   });
               });
           },
           //提交留言数据到数据库
           toLiuyan:function (req, res, next) {
               var form=new formidable.IncomingForm();
               form.parse(req,function (err, fields) {
                   if(err){
                       res.send({"bok":false,"curr":false,"msg":err});
                   }
                   if(fields.user.length && fields.msg.length){
                       var time=sd.format(new Date(),"YYYY-MM-DD hh:mm:ss");
                       //插入到数据库
                       db.insertOne("liuyan",{"username":fields.user,"msg":fields.msg,curtime:time},function (err, doc) {
                           if(err){
                               res.send({"bok":false,"curr":false,"msg":err});
                           }
                           res.send({"bok":true,"curr":true,"msg":"提交成功"});
                       });
                   }else{
                       res.send({"bok":false,"curr":true,"msg":"输入框内不能为空,请输入内容"});
                   }
               })
           },
           //删除数据
           deleteData:function (req, res, next) {
               db.deleteOne("liuyan",{_id:ObjectID(req.params.id)},function (err, doc) {
                   if(err){
                       res.send(err);
                   }
                   res.redirect("/liuyan");
               })
           }
       };
      

    相关文章

      网友评论

        本文标题:Node.js学习第七天笔记之登录注册项目和留言板项目

        本文链接:https://www.haomeiwen.com/subject/mvvqkqtx.html