Node.js学习第四、五天笔记之myAlbums项目实战

MVC

  • 指的是:models views controller;
    • models:用于后台数据的查找;
    • views:视图,用于存储浏览器页面的文件;
    • controller:管理者,控制者;用于二者之间的控制;

myAlbum项目开发

  • 创建文件夹:命令:mkdir
    • models:提供数据;
    • views:模板文件;
    • controller:控制器;
    • uploads:上传的文件
    • public:静态资源
  • 创建文件:命令:touch ; window命令行中使用type nul>
    • app.js:入口文件,创建服务器;
  • package.json文件:记录当前项目依赖;命令npm init -y;
  • 安装项目模块框架:命令npm install --save-dev express ejs formidable
  • controller文件夹下创建router.js文件;作为一个路由的控制器;
    • 知识点:在app.js中引入自定义模块,必须添加相对路径;如:const router=require("./controller/router");
    • 在router.js中设置代码输出参数;
     exports.showIndex=function (req, res) {
         res.render("index")
     };
    
    • 在app.js中直接引入:router.showIndex获取匿名函数;
  • 静态资源文件加载
    • 设置静态资源在public文件下:app.use(express.static("./public"));;即相对路径都在public目录下;
    • 在ejs文件中,通过link引入css文件和通过script引入js文件;都会发送对应的请求;请求地址为href和src中的路径地址;
    • 在通过get请求,打开index.ejs文件后,会在页面中继续发送请求;页面想要有css样式和js动效,必须保证css文件和js文件能够正常引入;如何在页面中渲染打开css文件;css的引入地址是很重要的;
    • 代码:app.use(express.static("./public"));中将静态资源的目录设置在public目录下,即所引入的css文件和js文件必须在此目录下添加相对路径,然后找到文件才能打开;
    • 所以,将css文件和js文件放在public文件夹下,在引入时添加相对路径;如:;注意:css前斜杠最好添加上,若不添加,会被拼接在地址的后面,会出错,所以必须添加;
    • 在地址栏中输入地址localhost:8080/css/bootstrap.css也可以打开引入的css文件;
  • 静态资源设置的含义
    • 代码:app.use(express.static("./public"))
    • 含义:在express中,设置静态资源的请求路径为public目录下;
    • 验证:在地址栏中输入localhost:8080/index.html地址,指的含义是查找到public目录下的index.html,打开并渲染到页面上;
    • 在index.html文件中有link引入的css文件;如:;其中link的href会发送请求;相当于在地址栏中输入localhost:8080/css/bootstrap.css地址;即,在public目录下查找css文件夹下的bootstrap.css文件,打开并渲染到页面中;
    • 结论:
      • 设置了静态资源的路径;则在地址栏中寻找的文件都是在public目录下查找,如果查找到,则渲染,查找不到,则会查看其它的请求是否存在此地址;
      • 打开html或ejs文件中,通过link或script或img中的href或src等引入文件,都会向服务器发送请求;会默认在public目录下查找;
  • 简单的实现index.ejs文件的页面打开渲染:
    • index.ejs文件,通过设置get请求:app.get("/",function(req,res){ res.render("index")};);即:在地址栏中输入"/",后可执行匿名函数;在匿名函数中通过res.render来默认打开views目录下的index.ejs文件;
    • 打开index.ejs文件后,里面引入的href和src再次发送多个请求;在设置的静态资源目录public文件夹下查找文件;然后打开渲染;
    • 代码:
      • index.ejs文件代码:
       
       
       
           
           模板
           
       
       
       

      你好,世界!

      • app.js服务器代码:
       const express=require("express");
       const app=express();
       const router=require("./controller/router");//引入自定义模块,必须添加相对路径;
       app.listen(8080);
       
       //发送请求,静态渲染页面
       app.use(express.static("./public"));
       //设置模板引擎
       app.set("view engine","ejs");
       //通过"/"来发送请求,打开views下的index.ejs文件
       app.get("/",router.showIndex);
      
      • router.js管理器代码:
       exports.showIndex=function (req, res) {
           res.render("index")
       };
      

项目开发

  • 搭建静态页面index.ejs;利用bootstrap模板来创建页面布局;
    • 页面中相册的个数取决于uploads目录下文件夹的个数;
    • 在页面中利用ejs模板创建for循环,在服务器中通过render()传送参数;即在router.js管理器中获取参数;router.js再去models中获取数据;然后最终传送给views中ejs页面;
  • 获取磁盘中uploads目录下文件夹的个数;
    • 在models中files.js中获取数据,导出数据;利用fs文件系统中的readdir()来获取文件夹下所有的文件,再通过fs.stat()获取每个文件的状态stats,判断stats.isDirectory()是否为true;如果文件是文件夹,则返回true;
    • 通过自执行函数和递归函数,将异步强制变成同步;然后待遍历完,输出数组;
    • 在匿名函数中如何输出文件:通过callback参数;注意传出的数据包括err错误信息;
    • 在router.js中引入自定义模块files.js,添加相对路径;通过匿名函数中的参数拿到文件夹信息;然后通过res.render()传送给ejs文件使用;
    • 注意点:
      • 在使用fs.readdir(path,()=>{})时,path路径为"./uploads",其中"./"拿到的是根目录;不是"../"拿到根目录;
      • 数据的输出通过回调函数,将异步操作中的结果输出,但要注意输出不同时刻的err信息;在成功输出数据时,赋值为null,这样在if(err)条件语句中,就不会走语句;
    • 代码:
      • ejs代码:
       
      <% for(var i=0; i
      文件夹图片
      <%= albums[i]%>
      <% }%>
      • app.js代码:app.get("/",router.showIndex);
      • router.js代码:
       //引入models中的files.js模块;
       const modFiles=require("../models/files");
       //显示首页
       exports.showIndex=function (req, res) {
           modFiles.showAllAlbums(function(err,albums){
               if(err){
                   res.send(err);
                   return;//阻断程序执行;
               }
               res.render("index",{
                   albums
               })
           });
       };
      
      • files.js代码:
       //用于生产数据,然后输给router.js使用;
       const fs=require("fs");
       exports.showAllAlbums=function (callback) {//数据以回调函数的形式输出;
           fs.readdir("./uploads",(err,files)=>{//地址为根目录下的地址;
               if(err){
                   callback(err,null);
                   return;
               }
               var ary=[];
               //把异步操作强制变成了同步操作;
               (function interator(i){
                   if(i>=files.length){
                       callback(null,ary);//null代表不会走if(err)条件;
                       return;//阻断程序执行;
                   }
                   fs.stat("./uploads/"+files[i],(err,stats)=>{
                       if(err){
                           callback(err,null);
                           return;
                       }
                       if(stats.isDirectory()){
                           ary.push(files[i]);
                       }
                       interator(++i);
                   })
               })(0);
           });
       };
      
  • 点击文件夹后发送请求,打开文件夹下的所有文件;
  • 页面的操作:
    • 提炼出两个ejs页面中的公共的代码,放在views下的include文件夹下的header.ejs文件中;这样在文件中引入此文件即可;
    • 优点:当页面公共部分的代码,发生变化,只需在header.ejs文件中修改即可,否则,还需分别再两个文件中修改;
    • 引入include.ejs文件代码:<% include include/header.ejs%>,其中include/header.ejs为相对路径,无需加引号;
  • 图片上传功能
    • 思路:
      • 创建form.ejs表单页面;通过form表单来提交数据;
      • 发送get请求,通过header.ejs中的上传a标签href设置地址,点击发送请求;打开form.ejs页面;传送数据;用于select表单中获取文件夹数据;
      • 发送post请求,通过表单中submit提交按钮,设置form中的action和method;点击发送post请求;
      • 在router.js中通过formidable模块来获取上传的数据;
        • 新建form对象;var form= new formidable.IncomingForm()
        • 设置上传地址;form.uploadDir="./uploads/"
        • 通过form.parse()拿数据;=》fields:表单上传参数组成的对象;files:表单file中name组成的对象;用于获取上传图片的路径名字;以及上传之前的名字;
        • 通过files.tupian.size,拿到上传文件的大小,然后进行判断,如果大于某值,则用fs.unlink()删除已经上传的文件;注意,在条件判断中设置return;阻断程序向下运行;
        • 通过fs.rename()将oldpath改为newpath,修改原来文件名字并移动该文件到新的路径下;
      • 修改成功后,打开对应文件夹的图集;调用modFiles.showAlbumsImgs(albumsImg,function (err,albums,albumsName){})
      • 修改成功后,可以通过 res.redirect("/中学")来进行重定向页面跳转;
    • 注意点:
      • 设置get请求"/upload"时,必须放在app.get("/:albumsImg",router.showImg);前面,否则,不会走该请求;必须将严格的请求放在不严格的请求的前面;
      • form表单中,seclect和file必须设置name值,否则无法获取数据;seclect的name值用来获取放在哪个文件夹下,file的name值是用来作为files对象中属性名来获取上传文件的数据的;
      • form表单中的action设置请求地址,method设置post请求,enctype设置大文件下的类型;
      • 利用formidable模块获取files对象后,path属性拿到的是路径加文件名;作为oldpath;newpath包含相对路径和文件名;相对路径设置为uploads下的对应文件夹中;
      • 在修改名字后,原来上传的文件会被移动到新的路径下;
      • 在设置上传地址时地址后面必须加"/",否则,无法使用;如form.uploadDir="./uploads/";
      • 注意异步和同步问题;
    • 代码:
      • form-upload.ejs代码:
       
       
       
           
           表单上传文件
           
       
       
       <% include include/header.ejs%>
       
      • app.js代码:
       /发送get请求:地址:"/upload",打开views下的form.ejs文件;
       app.get("/upload",router.upload);
       //发送post请求,地址:"/doupload",上传文件;
       app.post("/doupload",router.doUpload);
       //以上代码必须放在下面代码前面;
       //发送get请求:地址:"/大学",打开views下的showImg.ejs文件;
       app.get("/:albumsImg",router.showImg);
      
      • router.js代码:
       //上传文件获取数据
       exports.doUpload=function (req, res) {
           //新建一个form对象
           var form= new formidable.IncomingForm();
           //设置上传地址
           form.uploadDir="./uploads/";
           //解析文件
           form.parse(req,(err,fields,files)=>{
               //修改文件名,放在指定文件夹下
               var oldpath=files.tupian.path;
               var newpath=form.uploadDir+fields.wenjianjia+"/"+files.tupian.name;
               fs.rename(oldpath,newpath,function (err) {
                   if(err){
                       res.send("修改名字失败");
                       return;
                   }else{
                       //res.send("上传成功");//注意异步问题;所以此代码不能写在外面;
                       //当上传成功后,跳转到相应的文件夹中打开;
                       var albumsImg=fields.wenjianjia;
                       modFiles.showAlbumsImgs(albumsImg,function (err,albums,albumsName) {
                           //如果有错误,则显示在页面上,并阻断程序执行;
                           if(err){
                               res.send(err);//send后面可以写return;
                               return;//必须阻断程序执行;
                           }
                           res.render("showImg",{
                               albumsImg,
                               albums,
                               albumsName
                           })
                       });
                   }
               })
           });
       };
      
  • 接盘侠
    • 在最后设置use请求,请求地址为"/",即所有的地址都可以进入请求;渲染打开404.ejs文件,显示404页面;
    • 代码:
     //设置404页面,用来接底
     app.use("/",function (req, res) {
         res.render("404");//打开404.ejs文件;
     });
    
    • 利用middleware中间件来设置错误流,当进入一个请求后,如果出现err,则通过next(),来向下接着请求,最终到达use请求,渲染404页面;
    • 在router.js文件中所有请求的匿名函数;均要设置next,当err情况下,设置next(),并阻断程序执行;
    • files.js文件中err不需要设置next(),因为通过callback已经将err返回到router.js中;
    • 这样设置,也可以解决地址具体地址和广泛地址的影响;
    • 注意:send()后面不能设置任何东西;可以写return;

项目开发中的架构格局

  • 文件分类及作用
    • MVC结构:
      • M:models:用来获取后台的数据库,通过exports输出给controller管理器;
        • 创建files.js文件,作为后台数据的模块;通过exports来传出数据,在router.js管理器中引入此模块,用于获取传出数据;
      • V:views: 目录下存在ejs文件,作为浏览器视图的渲染文件;
        • 存储ejs文件,用于页面的打开渲染;
        • 创建include文件夹,里面创建header.ejs文件,作为ejs文件的公共部分代码;通过<% include include/header.ejs%>引入到其他文件中;
      • C:controller:管理器;用来连接models和views;
        • 作用:作为一个管理者,在views中通过render来打开ejs文件,在数据库或models中拿数据;
        • 创建router.js文件,作为数据的管理器;通过exports来传出数据;在app.js中引入此模块来获取数据;
        • 创建package.json文件,通过设置里面的main属性,来设置默认入口文件router.js;则在app.js服务器文件中引入模块时,可以直接引入controller文件夹,如const router=require("./controller");
      • 三者之间的关系:
        • 当服务器中接受到浏览器发送的请求后,向controller管理器请求;如代码:app.get("/",router.showIndex);;router.js中设置匿名函数;渲染页面;
        • 当浏览器中需要uploads文件夹下的文件夹个数时,向controller管理器要数据;controller再向models后台数据库中查找获取;models数据也通过exports输出数据;
    • public文件夹:用于存储静态文件;如css,js文件;通过在服务器中设置静态渲染来引用文件;
    • app.js:为入口文件,用于创建服务器来前后台交互;
    • package.json:用于记录项目依赖的文件;
    • readme.md:读者读的文档,用于解读项目;
  • 请求及目的
    • get请求,是为了渲染打开页面;
      • get-"/"=>打开index.ejs;即,打开图片首页,根据uploads下文件夹的个数,呈现出相应个数的图集;
      • get-"/:albumsImg" => 打开showImg.ejs;即呈现出每个albumsImg文件夹下的图片;
      • get-"/upload" => 打开form上传文件表单;用于上传图片文件;
    • post请求,是真正做一些功能的,如上传文件;
      • post-"/doupload" => 通过表单中的submit提交按钮,来发送post请求,进行图片文件的上传;
    • use请求:请求地址设置为"/",可以省略,作为接盘侠;
      • use-"/" => 打开404.ejs文件,呈现404页面,配合middleware中间件使用;

项目开发中的知识点

  • 在controller文件夹中创建package.json文件,里面设置main属性,来设置默认的入口文件为router.js,这样在app.js服务器中引入模块时,只引入文件夹controller;即:const router=require("./controller");
  • 在项目开发中如果匿名函数中存在err错误代码,必须设置相应的条件语句,然后传出错误信息;后面一定要加return,阻断程序执行;
  • 使用req.params.albumsImg获取请求地址时,除了文件夹地址,还会得到favicon.ico,所以需要在获取文件夹下文件的函数中,阻止favicon.ico运行;
  • 1M等于1024K,1K等于1024字节,文件上传时,通过files.tupian.size来获取上传文件的大小,单位为字节;
  • 接盘use请求和middleware的设置
    • use请求地址为"/",可以省略;当所有请求都不成立的时候,最后请求use的匿名函数,打开404页面文件;
    • 前提是在每个请求的匿名函数中设置middleware中间件;即next();当err时设置next(),并阻断程序执行;

你可能感兴趣的:(Node.js学习第四、五天笔记之myAlbums项目实战)