Node.js学习第九、十天笔记之论坛项目

分析论坛项目

  • 数据库:总共两个
    1. users:用户数据,管理用户资料信息;
      • 用户名;
      • 密码
      • 头像
    2. comment:评论数据,管理用户的评论信息;
      • 用户名
      • 头像
      • 留言内容
      • 时间
  • 功能
    1. top部分:--公用的;--include
      • 未登录:logo,全部说说,注册,登录;
        • 注册功能;跳转注册页面;
        • 登录功能;
      • 已登录:logo,全部说说,我的说说,用户列表 欢迎您xxx 设置
        • 设置功能:
          • 个人资料:跳转文件上传页面;图片上传,图片裁切;
          • 退出功能;
    2. index页面
      • 登录前
        • 欢迎注册:通过点击按钮跳转到注册页面
        • 欢迎登录:直接登录;
      • 登录后
        • 左边:头像
        • 右边:
          • 上面:欢迎你:xxx;
          • 留言框:
          • 发布留言的按钮;
    3. 底部评论区
      • 无论是否登录,都有留言列表:头像,用户名,内容,时间;
    4. 我的说说--必须先登录才能看到
      • 上面:头像 xxx的个人主页
      • 下面:当前登录者的所有留言和留言时间以及删除按钮
    5. 用户列表
      • 上面:用户列表
      • 下面:头像和用户名;

项目制作前的准备

  • 项目文件夹及文件
    • MVC结构
      • M:models => mongodb.js mongodb-setting.js md5.js
      • V:views => pub(top.ejs,footer.ejs) cut.ejs index.ejs login.ejs mycom.ejs mycom.ejs reg.ejs upfile.ejs userlist.ejs
      • C:controller => router.js package.json;
    • mongoDB:数据库
    • public:静态资源目录,css,img,js
    • avator:头像存储目录,设置静态资源目录;
    • node_modules:第三方模块存储;
    • package.json:项目初始化文件记录信息;
    • app.js:服务器
    • readme.txt:文档信息;
  • 安装的第三方模块
    • express mongodb ejs silly-datetime gm formidable express-session
  • 静态资源文件
    • bootstrap jQuery
    • 截图的css和js文件

项目制作

  • 思路

    1. 首页的制作,index.ejs文件的制作
      • 页面展现前,必须设置静态资源目录,设置在public目录下;用于引入ico图标和js,css文件;
      • 渲染页面前设置ejs模板引擎;
      • 发送请求:地址栏发送get请求,请求"/forum",然后render渲染首页;
      • 提取公共部分,头部和尾部放在top.ejs和footer.ejs文件中,放在views文件在pub中,通过include引入;
    2. 页面顶部搭建好未登录状态下的静态页面;
    3. 注册功能
      • 通过top顶部中的注册按钮,发送get请求,请求:"/reg",渲染页面;
      • 制作静态页面,通过ajax发送post请求,提交注册数据;
      • 点击注册页面中的提交按钮,ajax发送post请求,请求:"/doreg",提交数据;
      • 管理器router.js中接收数据,用formidable接受post请求发送的数据;通过mongodb封装的函数,插入到数据库的users集合中;
      • 插入的数据有:用户名,密码(加密后的密码),默认的图片地址;
        • 注意:在插入数据库之前,必须在数据库中查找username是否存在,如果不存在,在插入;
        • 插入成功后,必须设置session;设置session的login,username,imgpath;
      • 注册成功后,跳转到首页;window.location.href="/forum";
    4. 登录功能
      • 通过top顶部的登录按钮,发送get请求,请求:"/login";渲染页面
      • 制作静态页面,通过ajax发送请求,请求:"/dologin";提交登录数据
      • 服务器接收数据后,通过db.find()查找是否存在数据,当数据存在的时候,再校验密码;
      • 校验成功后,登录成功,但是要设置session,其中imgpath为数据库中存的值;
    5. 未登录和已登录状态下,页面的显示不同
      • 通过ejs中的花式赋值,设置条件判断
      • 判断条件是:session设置中的login的赋值;
      • 未登录状态,session中的login不存在,或者被赋值为false(在退出登录时);登录状态下,赋值为true;
      • 所以通过条件判断,来决定那部分元素显示,那部分元素隐藏,通过curent的设置,来让那个元素点亮;
      • 要求:只要涉及到login的值的情况下,在渲染页面时,必须传参;
    6. 退出登录功能
      • 点击设置中的退出登录按钮,通过a标签中的href发送get请求,请求"/logout";
      • 服务器中设置session的值,将login设置为false,将username设置为空;
      • 通过res.redirect()重定向刷新首页;如:res.redirect("/forum");
    7. 修改头像—上传头像文件
      • 点击设置中的修改头像按钮,通过href发送get请求,请求"/upfile",然后渲染页面;
      • 渲染页面之前,要进行判断,判断当前状态是否为登录状态,即session.username是否存在;如果存在,再渲染页面,传入参数,如果不存在,提醒去登录;
      • 页面渲染后,通过上传按钮的点击事件,发送ajax的post请求,请求:"/doupFile",上传文件;
        • 注意:
          1)此时form表单中设置enctype为"multipart/form-data";用于大文件上传;
          2)ajax上传file文件,data设置必须为:data:new FormData($('#formid')[0]),这样才能在服务器端通过files来获取文件信息,与form表单提交相同;
      • 上传图片后,通过fs中的rename来修改上传到文件路径和名称;然后放在avatar目录下;
      • 上传成功后,先不对数据库中的图片地址进行修改;
      • 在前端中ajax的success函数中跳转切图页面;
    8. 切图功能
      • 通过upfile.ejs中ajax请求成功后的success函数中,跳转页面发送请求;请求"/cut";渲染页面
      • 在渲染页面前,对session.username进行判断;确保在登录状态下,才能进行裁切;
      • 注意:在渲染切图页面时,需要传参,此时的imgpath不能使用session.imgpath,因为此时需要裁切的是刚刚上传上来的图片,不是数据库中的原图片;所以此时需要拿到上传功能中的图片新名称,所以需要设置全局变量;
      • 在页面设置中,通过静态目录打开avatar目录下刚刚上传后的图片;
      • 引入切图页面的所有文件css和js,放入到public目录下;引入文件;
      • 裁切功能
        • 点击截图按钮,通过ajax发送get请求,请求:"/docut";提交裁切的数据;
        • 裁切数据通过data设置,主要拿的是,裁切后图片的宽,高,左边距,上边距;
        • 考虑到,上传的图片大小都不同,所以需要设定显示在页面上的宽度,所以需要算出比例,让参数乘以对应比例后,才能对原图片裁切,否则,尺寸会出错;
        • 服务器端拿到数据后,通过gm模块来对原图进行裁切,然后再放在原来的路径下;
      • 裁切成功后,对当前用户在数据库中的imgpath进行修改,通过username进行查找,设置imgpath值,需注意的是,使用$set来进行部分设置,否则,就会被全部覆盖;
      • 当数据库中imgpath修改成功后,必须对session中的imgpath值进行修改;此时证明切图成功;
      • 切图成功后,在success中,跳转回首页;
    9. 提交留言功能
      • 在首页中,制作留言页面;通过判断login的值,在当登录状态下,使其显示;
      • 点击提交按钮,发送ajax请求;请求:"/docom",服务器端获取上传的数据,然后插入到数据库的comments集合中;
      • 插入的数据:用户名,图像名称,内容,时间戳;参数通过session来拿username和imgpath;
      • 插入数据成功后,在success中,刷新首页;
    10. 留言板制作
      • 页面无论在登录还是在未登录的状态下,首页刷新后,就会显示留言信息;
      • 需要对数据进行排序和分页显示;
    11. 获取所有数据的总个数,用于分页;
      • 页面一刷新,就通过ajax发送get请求,请求:"/getcount",获取数据总个数,返回success中;
      • 设置变量pageamount,每页展示多少个数据,然后计算出页码个数;
      • for循环,通过字符串拼接,在DOM插入分页;
    12. 制作页面结构;封装一个函数getData(n),其中n的值为page值;即哪一页;
      • 函数中通过ajax发送请求,请求:"/getcom",获取指定的数据,通过传入page和pageamount来获取指定页码的数据,获取到的数据为一个数组,每一个元素均为一个对象,遍历数组,通过字符串拼接插入DOM中;
      • 函数需要传实参n,来获取第几页的数据,从0开始,n为0,则代表第1页;
      • 在页面结构制作中,设置了一个显示详情的按钮;
        • 点击按钮时,弹出模态框,显示详细信息;
        • 注意:模态框中的点击按钮中的data-target设置的值必须与弹出框的id值一致,并且要求,每条数据的id值不能相同;可以使用数据自己的"_id"值;
    13. 首页加载,默认显示第一页的数据,第一个分页点亮
      • 在插入DOM后,获取所有分页元素,添加类名active,来点亮第一个;注意:jQuery中无DOM映射,所以需要在页面DOM元素改变后,重新获取元素;
      • 调用函数getData(),传入实参为0,即显示第一页数据;
    14. 点击页码,显示该页码数据
      • 对每个页码元素添加点击事件;
      • 点击事件触发,通过index()获取该点击元素的索引值,然后作为实参,调用getData()函数,然后获取该页码的数据,插入到页面中,进行更新;然后给该元素添加active类名,将其点亮,其余的元素删除类名;
    15. 我的说说页面
      • 点击top中的我的说说按钮,通过href发送get请求,请求:"/mycom";然后渲染页面;
      • 渲染页面时判断是否在登录状态;
      • 渲染页面时,需要传入参数:login,username,imgpath,current;
      • 页面加载后,通过ajax发送get请求,请求:"/getmycom",获取该用户的所有数据;
      • 获取数据后,遍历插入DOM中显示;
      • 我的说说页面中每条数据后,设置了删除按钮;
        • 点击删除按钮,通过href发送get请求,请求:"/delete/${this._id}";
        • 通过每条数据唯一的"_id"值,来发送请求;
        • 在服务器端设置get请求的地址为:"/delete/:id";代表id的取值可以是任何值;
        • 通过req.params.id来获取请求地址中的id值,也就是获得每条数据的"_id"值;
        • 通过db.deleteMany()函数查找删除数据,在查找数据时,需要引入objectId模块,来处理id值;
        • 查找的数据:{_id:objectId(req.params.id)};
        • 删除成功后,在前端页面弹出删除成功,通过window.location.href跳转刷新我的说说页面;
    16. 用户列表页面
      • 用户列表在未登录状态下,就显示,所以,在渲染页面时,无需判断是否在登录状态;
      • 点击top中的用户列表按钮,发送get请求,请求:"/userlist",渲染页面,传入参数;
      • 页面加载后,通过ajax发送get请求,请求:"/getuserlist",获取users集合下的数据;
      • 数据获取后,遍历插入DOM中,页面中需要username和imgpath数据;
    17. 404页面
      • 设置use请求,请求地址为"/",则在输入地址错误时,渲染404页面;
  • 知识点:

    • session的设置,在整个项目中,起到决定性作用,登录状态与未登录状态下,通过判断session.login的值,来在ejs中进行条件判断,然后让哪些元素显示;
    • 通过获取session.username的值,就能获取到当前登录状态下的用户名,进而去查找数据;
    • 所有的操作,就是在刷新首页,当首页刷新时,会通过login的值,来进行判断,然后显示页面元素;进而展现出登录与未登录的状态;
    • 在注册和登录的代码中,无论是插入数据还是校验数据,当成功后,都对session的login,username,imgpath进行重新赋值,然后,发送请求"/forum",也就是刷新首页,通过被修改后的值,来判断哪些元素显示,进而呈现出哪种状态;
    • 在top顶部导航中控制哪个元素被点亮,通过设置current参数,渲染页面时,传入current值;
    • 在前端中发送请求,刷新页面,用到的代码:window.location.href="/forum"
    • 在服务器端发送请求,刷新页面,用到的代码:res.redirect("/forum")
    • 上传文件时,ajax发送post请求,file文件参数上传时,data必须设置为data:new FormData($('#formid')[0]),不能用key=val键值对设置,具体使用请见链接:Ajax通过FormData上传文件
    • avatar文件夹中存放的时数据库中存的头像名称所对应的文件;所以需要设置静态资源目录,才能展现这些图片;
      • 设置静态资源目录:app.use("/avatars",express.static("./avatar"));含义是,在img中src设置时,需要将文件放在avatar目录下,但是在设置时,需要在前面加上"/avatars",然后加上目录下的相对路径;
    • icon图标的设置:<link rel="icon" href="/img/icon.jpg">,静态资源目录下的相对路径;
  • 注意点:

    • 只要进行页面渲染时,render中就必须传参;否则,页面不会正常展现;
    • 注册和登录时,都适用post请求,安全性更高,get请求,会将用户名和密码显示在地址栏中,不安全;
    • 上传文件和截图两个页面在渲染时,必须对session.username进行判断,确定在登录状态下,才能进行,否则,不能进行,提醒登录;
    • 头像在数据库中存的是文件名;所以在显示图片时,只需将数据库中的对应地址拿出来,放在src中;但是需注意的是,要设置静态资源目录,要跟use中前面设置的地址一直,并将其放在后面的目录下,在引用时,前面必须加前缀;如此项目中,设置静态资源时,设置了"/avatar",在引用时,必须加此前缀,后面加目录下的相对路径;
    • 上传文件后,不对数据库中的imgpath进行修改,必须在截图功能成功后,在能对数据库进行修改;为了防止当上传文件后,不对文件进行裁切,就直接回到首页,然后图片会显示原来的尺寸,页面会很难看,所以,只要不修改数据库,也不能修改session中的imgpath,页面中就不会显示刚刚上传的图片;
    • 上传文件的功能:图片在上传时,先上传到uploads文件夹中,只有在裁切图片后,才能放在avatar文件夹下,图片在加载时,静态资源目录也要设置在avatar文件夹下;注:设置静态资源路径时,不要只设置为"/",要设置特定的路径"/avatar";
    • 在截图功能中,需要打开图片,所以必须赋值上传功能中的图片新名字;这样才能拿到新图片,不能设置session中的imgpath,这样拿到的是修改头像之前的图片;
    • 在数据中的页面详情设置中,使用了模态框,在设置模态框中的点击按钮的data-target的值时,要求其必须与弹出框的id值一致,并且要求每条数据的id值不能相同;可以使用数据自己的"_id"值;
    • 在上传的文件修改名字时,使用fs.rename时,newpath设置时,是通过"./"来获取根目录,然后在设置相对路径;
    • 在使用gm()截图时,路径也是通过"./"来获取根目录,然后设置相对路径找文件;
  • 项目改善

    1. 问题:在上传文件后,会将avatar目录下的原图片修改掉,所以不管改不改数据库,或者是否该session.imgpath,此时session.imgpath有可能是新的名字了;所以在刷新首页的时候,上传的文件还会显示,页面会难看;
      • 改善:
        • 上传文件的存储目录,必须设置一个新的目录,作为中间目录,上传文件修改名字后,放在此目录中;就不会对avatar中的原图片进行覆盖,不截图的情况下,还会显示原来的图片;
        • 截图功能中,需要将上传的文件进行打开裁切,可以在设置一个静态资源目录,专门存储上传的文件,然后再cut.ejs中打开上传文件时,就可以写新设置的静态资源目录下的相对路径了;
        • 在服务器端切图时,gm中的原地址,写上传文件存储地址,注意此时通过"./"拿到根目录,然后进行相对路径查找,跟静态资源目录的查找不同;在裁切完后,write中的路径需要存储在avatar目录中;覆盖原来图像;
        • 此时就完成了修改图像的功能,然后再修改数据库,修改数据库成功后,必须重新设置session.imgpath值;
    2. 问题:在切图后,会修改图片,进而修改数据库中的图片地址,但是在此数据库中两个集合中,都存了图像的地址,如果需要更改,两个集合都需要修改;所以会出现问题;
    • 改善:在users集合中,不再插入 图片地址信息,在页面渲染时,都会传入imgpath值,此时的值为session设置的值,所以,在comments数据库中imgpath数据修改后,需要重新设置session中的imgpath值;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351