• node=day6


    (1)反馈

      

       

       

    (2)项目结构

      1、新建项目文件目录forum(社区)

      2、初始化项目,新建项目说明文件package.json

        

      3、初始化git仓库,用于后期向git推送发布

        

      4、新建项目说明文档README.md,后期在Git上也可以浏览

        

       5、创建git上传忽略文件类型设置文件“.gitignore”

        

       6、安装核心包Express(开启创建服务)、mongoose(数据库)

        

         下载完毕后会发现,npm新版在安装第三方依赖时,会自动创建package-lock.json锁文件,将记录依赖树,锁定版本

       7、创建静态资源开放目录public,给客户端用

        

       8、创建入口文件,编写代码

    注意:这里需要开放静态资源public,同时因为后期要用jquery和bootstrap,所以这里开放node_modules目录,让前端直接访问该目录下的资源

        

         查看Express官方文档会发现开放静态资源有个写法

        

         这里可以对上述代码做下修改

        

         这里注意:path为核心模块(路径操作模块),所以需要引入,接下来便可以通过url浏览静态资源。如下所示

        

         

    上面path.join(__dirname,'./public')与之前相比,是将路径变为绝对路径。这里 便涉及到两个知识点:path路径操作模块和__dirname文件路径。接下来做下介绍

    (3)path路径操作模块

      详情参见path路径操作模块.

    (4)dirname和filename

      详情参见node中其他成员(非模块成员)之dirname和filename.

      

    (5)art-template模板引擎中的include-extend-block

      1、接下来开始渲染页面,此时需要配合模板引擎

    因为这里用的Express搭建的服务,所以需要用到模板引擎express-art-template,同时还需要art-template。因为express-art-template是基于art-template开发的
    新版npm5.xxx之后不需要加--save参数,即可默认加上

          

      2、接下来启动服务,配置模板引擎相关参数

        

    注意:这里避免相对路径,使用动态绝对路径

        

        index.html内容:

        

         启动后,测试如下

        

        因为放在了public开放目录下,所以也可以通过开放资源url访问

        

         接下来加个模板参数进行渲染

      3、模板参数渲染

        

        

        结果如下所示

        

         

    对比分析可得静态资源经过了模板编译,此时渲染成了我们想要的内容 

      4、公共部分抽离

    分析可得在开发中,有的地方例如网页头部导航和底部,在很多页面用到,此时便可以抽取出来

        接下来打开art-template官网文档,查看相关配置(这里选择简体中文,方便阅读)

        

         然后查找语法

        

         接下来看下子模板和模板继承

        ①首先新建文件header.html

        

         

         ②接下来在其他页面(同级index.html)引入

        

        

         ③同理,建立公共底部模板文件footer.html

         

         

         

         渲染结果如下

        

           ④进一步封装,目前为止已经把头部、底部抽离出去,但还有很多架构一样

        

    此时便可以利用模板继承

        ⑤模板继承

    接下来新建布局模板layout.html,将原来的index.html文件内容粘贴过去做下修改

        

         接下来在index.html页面去继承

        

         此时页面渲染结果如下

        

    分析:因为index.html没有填入内容,所以这里展示默认内容

        ⑥接下来开始填坑

        

    分析可知:填坑内容与留坑语法类似,此时结果如下

        

         ⑦公共模板完善

        因为接下来要用到bootstrap和jquery,所以直接在公共模板页面引入,首先下载第三方依赖包

        

        补充(dist发布目录):

        

         

         查看效果,发现文件引入成功,字体样式已经改动

        

    此时模板页和后代子页面都已经整合到一起

      5、art-template多环境应用

    模板引擎art-template可以在node服务器环境应用,也可以在浏览器环境应用,原因在于源码里没有涉及具体环境API(模板引擎只操作字符串,与DOM操作、文件操作均无关

      6、其他相关模板引擎

       

      7、公共模板页的设计

    关于公共模板页layout.html的设计主要注意:
        1、将公共部分放到这里
        2、在需要后代继承覆盖的地方留坑,并加上“默认内容”

        为了后代各个页面拥有自己的样式和脚本,所以还需要在样式和脚本处留坑,但这里注意:默认位置,后期会被覆盖,也可以不填,之后再做修改

        

         接下来在index.html对应填坑即可

        

         

         对于脚本部分,为了防止混淆,我们可以命名为script  

        

         这里对于留坑位置做下修改,都给去掉

        

         然后在index页面做下样式定制

        

         此时网页记载完毕后的内容如下

        

      

    (6)案例资源页面

      这里便涉及到文件分类和命名,之所以用_,是因为要和其他业务主页面区分开来

      

       对于公共页面局部,可以抽离归类到相关文件夹,例如_layouts(布局)目录,存放如下(因为可能有多个公共模板,所以命名为layouts)

      

      _partials(部分)目录,存放如下,存放公共头部、尾部、导航等

      

       所以接下来依次编写静态页面,即静态资源页面设计和命名,详见node(day6)之静态资源页面设计和命名.

    (7)设计注册、登录、退出路由

      

       相对之前来说多了几个目录controllers、models、routes等。

      

       接下来设计下路由

      

    注意:有些功能是需要权限的,例如发布一篇博客,如果不登录是无法发表的

      

    (8)配置注册登录路由

      1、路由提取

    正如之前所讲,入口文件不做路由处理

      

    一般小型项目,可以直接在根目录下新建router.js处理路由。
    但当项目较大,请求越来越多时,最好将其在routes目录下分类管理。
        例如:注册登录退出相关的操作,放到routes下的session.js(会话),因为注册登录退出操作,都相当于在和服务器进行会话
         新建话题、删除话题、修改话题、查看话题列表等操作,放到routes下的topic.js

      例如:这里在routes/router.js设计渲染首页路由,如下所示(      备注:后期修改为routes下各个子文件操作,然后通过routes/router.js统一管理              )

      

       接下来在入口文件require引入加载并use使用

       

      2、接下来添加其他路由操作

      

       之后进行验证,点击登录、注册按钮跳转到相应页面即可

      

    (9)快速启动配置

    为了快速启动项目,接下来在项目说明文件配置scripts项,如下所示

        

      配置完毕后,以后再启动项目只需输入指令“npm start”

      

    (10)处理注册页面,配置Express中间件body-parser

      接下来看下注册页模板内容

      

       点击提交时利用jQuery操作表单提交,所以这里需要引入jquery

      

    serialize() 方法通过序列化表单值创建 URL 编码文本字符串,
    序列化的值可在生成 AJAX 请求时用于 URL 查询字符串中
    关于jQuery的ajax里dataType预期服务器返回数据类型,详见jQuery的ajax里dataType预期服务器返回数据类型.

      这里的data为序列化后的表单数据,打印如下

      

       接下来获取表单post提交数据,这时便需要配置body-parser中间件

      

       1、下载body-parser中间件

        

      2、在入口文件进行相关配置,注意:一定要放在挂载路由之前配置

        

        此时在路由配置文件输出打印post提交数据

        

         测试如下:

        

         

         如果body-parser配置放到了挂载路由到app实例之前,则获取不到post提交数据

        

         接下来便要开始操作数据库,这里我们使用mongoose第三方包实现,首先要设计数据模型

    (11)设计数据库(用户数据模型)

       1、分析

    因为除了用户数据,还有话题相关数据、评论相关数据等,所以这里需要设计多个数据模型,将其放到models目录下

        

         models下有多个数据模型,代表多个集合。user.js代表用户数据集合

      2、设计user.js用户数据集合

    注意:集合命名为大写单数User,最终数据库集合名会变为小写复数users

        

      3、设计文档格式

        首先是基本信息

        

         另外,除了基本信息,还有些看不到的信息,例如创建时间、修改时间... ...,这里加入创建即注册时间

        

         重点分析:

        

    这里可能会有疑问:为什么Date.now没有加函数执行符?
      原因:加入函数执行符会即时调用

        

    这里传入方法Date.now,当你去new Model时即实例化模型,如果没有传递create_time,则mongoose就会调用default指定的Date.now方法使用其返回值作为默认值
    对比分析:例如type为a+b,则在new Schema时便自动计算出结果

        

    同理,在创建时间处,如果加入函数执行符,则会立即执行。这时变成了写死的时间

        

       接下来设计修改时间文档格式

        

       此外还有用户头像avatar,在用户信息设置处有个默认头像

      

       

       此外,在用户信息设置里还有介绍bio

      

       加下来还有性别gender

      

       接下来还有生日,生日这里不用加默认值

      

    接下来结合业务逻辑需求,看下还需要哪些数据,如下所示

      

       

       分析完毕后,此外还有账户状态status。例如管理员管理用户状态,禁言、封号等等... ...

      

    此外也可以通过mongoose框架模型层次,对数据格式做限制,例如email必须为邮箱格式、昵称nickname长度不能超过10位等等... ...,需要用到验证中间件,后期介绍

      

    (12)处理注册请求

      1、开启数据库服务,连接数据库

        

      2、基于之前设计的用户数据模型,进行业务操作(注册、登录等)

        注册即为保存数据、登录为查询数据

        在正式操作前,首先在编码里连接数据库

        

         目前为止先写到这里,但操作其他数据时(topic.js、comment.js)还需要再次连接,肯定不合适

        所以这里做下修改,新建mongoose.js操作数据库,如下所示

    /*1、引包*/
    var mongoose = require('mongoose')
    
    var db_url = 'mongodb://localhost/blog'
    /*2、连接数据库*/
    /*mongoose.connect('mongodb://localhost:27017/0204')默认开启的端口为27017*/
    mongoose.connect(db_url)/*这里也可以将端口去掉,默认便是27017*/
    /* 链接成功 */
    mongoose.connection.on('connected', function() {
      console.log('Mongoose connection open to ' + db_url);
    });
    /* 链接异常 */
    mongoose.connection.on('error', function(error) {
      console.log('Mongoose connection error:' + err);
    });
    /* 链接断开 */
    mongoose.connection.on('disconnected', function() {
      console.log('Mongoose connection disconnected');
    });
    
    module.exports = mongoose;

        之后在其他文件调用即可

        

         

         首先查询用户邮箱是否存在,然后查询用户昵称是否存在。这里我们使用fAPI为indOne,find方法即使只查出一个,也会将其放入数组

        

         如果邮箱已经存在,接下来需要判断昵称,查询文档,找到or操作

        

         

         所以接下来利用or

          

         接下来直接判断“邮箱或者昵称是否重复。如果两者有一个存在则提示,邮箱或者昵称已存在”

    当然可能有的网站在切换输入框时便直接判断,这样的话需要将邮箱、昵称分开编写API接口

        

    注意:这里res.send()返回结果需要结合客户端代码进行分析。
        如下所示,查看后即可得知,该操作是表单操作post异步请求,需要服务端返回JSON数据,之后客户端根据JSON内容进行业务交互

        

        接下来做下测试

        

         

    此时发现客户端没有输出,服务端执行到了OK。
    那么问题来了:服务端发送了响应数据,为什么客户端没有输出呢?(服务端发送了响应数据为ok,如下所示)

        

    原因:客户端ajax里指定期望服务器返回数据格式dataType为json,但服务端发送的不是json。所以客户端解析不到,所以客户端没有报错,也看不见
      接下来做下测试,给客户端发送响应数据,格式为json

        

         此时在做下测试,点击注册按钮后,便可以发现客户端打印数据

        

    分析:jQuery的ajax里的dataType:json的作用为
        预期后台返回结果为json字符串,如果返回的是json字符串,那么直接将其解析转为js可操作的对象,结合文章jQuery的ajax里dataType预期服务器返回数据类型.理解

        如果后台返回结果为字符串,而不是json格式字符串,那么无法进行转换,如下所示

        

         如果这里是纯字符串,那么肯定无法正常转换。但客户端里面尝试转换对象格式失败,虽然无法正常输出,但也不会报错

      3、后台发送json格式响应

        如下所示,直接发送json格式响应

        

         所以这里使用JSON.stringify()进行转换

        

         此时注册页面提交后便可以输出后台发送的响应

        

      4、Express框架的json方法

        再在响应里添加数据,测试如下

        

         

         都可以正常获取服务器返回响应,但是这样操作也过于繁琐,Express封装了json方法可以直接转换

        

        测试如下:

        

    Express的响应方法json方法会自动将里面的对象转换为json字符串,也就免去了手动转换

        小结:

        

      5、json响应方法替换send

        接下来将之前的send响应方法都替换为json,然后统一响应格式.

        

         这里注意:error中属于服务器错误所以success为false,而邮箱或者昵称已经存在属于业务操作,都已经完成对比,所以状态码为200

      6、保存数据到数据库 

        如果数据没有问题,则保存数据到数据库

        

         接下来做下测试,注册页面填写信息提交,然后连接数据库进行查询

        

        

         再次点击注册,客户端输出结果如下(邮箱或昵称已存在email or nickname already exist)

        

      7、服务端自定义业务状态码

    接下来开始在客户端根据服务端返回响应进行操作,但此时仍然存在问题

        

         即返回状态码都为200或者500,无法准确获取响应结果。此时便需要在服务端设计一些自定义的业务状态码... ...

        虽然也可以根据字符message判断,但字符可控性太差,所以还是推荐自定义业务状态码

    接下来将success改为error_code,然后自定义值
    500为错误,1为邮箱或昵称已存在,0位成功... ...

        

    因此这里便需要接口文档进行前后端协同开发,统一规定自定义业务状态码

      8、客户端接收响应,针对性处理

        

         测试如下(再次提交时便会提示,信息已经存在)

        

        此时可以用CMD或者MongoDB的可视化操作工具进行预览,接下来可以启动预览

        

        CMD操作如下

         

       9、密码加密md5

        此时可以从数据库直接看到密码,但像密码这种隐私数据,一般存储时都是md5加密(php、node、java等任何语言都可以加密操作)

        目的:防止数据库信息泄露,用户密码曝光

    这里便需要用到第三方包,Github有很多种,选择一种即可

        

        这里例如选择第一个

        

         这里附上GitHub中文社区,进入直接搜索md5即可GitHub中文社区

         接下来开始安装使用

        

         接下里引入使用

        

         然后在存储数据之前对密码进行二次加密,当然也可以多层加密,提高安全性。一层加密的话加密程度低,建议至少两层

        

         接下来做下测试(密码为123456)

        

        注册成功后查看数据库,此时发现密码为加密后的数据

        

         注意:

    登录时输入的密码不能直接和数据库存储的加密密码比对,都是拿着加密的密码进行比对。
    且只能正向加密,不能反向解密。所以,即使是开发人员,也无从得知用户密码

         

    (13)表单同步提交和异步提交

      1、分析

        从特性上将,表单具有默认的提交行为,默认是同步的,即同步表单提交,浏览器会锁死(转圈... ...),等待服务端的响应结果

        接下来做下对比分析

      2、异步提交,首先看下案例里的异步提交

        

    异步表单提交:form标签内部不再编写action和method,而是通过ajax的url和method选项去实现提交

      3、同步提交

        

         同步提交时不再需要ajax,而是直接在form表单的开始标签里添加action和method属性实现,接下来开始进行注册

        

         点击提交按钮

        

        再次刷新页面,内容如下

        

      4、区别

        同步提交表单内容会导致浏览器锁死,异步提交表单内容不会发生锁死,浏览器任然可以干别的事情

        详情参见文章浅谈表单同步提交和异步提交.

    (14)服务端重定向,针对异步请求无效

    当注册成功后,应该重定向到登录页面

      

       目前为止,只是弹框提示

      注意:如果客户端是异步请求,服务端重定向针对异步请求无效。如下所示,如果改为重定向或者res.render()、res.send()都会无效,无法跳转重定向。

      即如果是异步请求服务端无法重定向,对比之前的表单同步请求则可以实现跳转重定向

      

      

       所以如果想实现重定向,必须由客户端实现。如下所示

      

      关于页面重定向知识点,如下所示

      

    (15)登录功能

      1、首先编写html模板代码

        

        接下来编写脚本代码,获取表单输入提交内容,并且阻止表单默认提交事件

        

         测试如下

        

      2、发送AJAX请求,执行异步提交操作

        注意:一般为了防止他人暴力破解,不会专门提示邮箱错误或者密码错误。

        场景:他人在输入邮箱和密码后提示密码错误,则可以知道,该账号一定存在,接下来只破解密码即可,增加了用户账号风险。如下所示

        

         所以一般会提示“邮箱或者密码错误”,所以编写ajax请求如下

        

      3、处理登录操作服务端

    登录界面渲染已经没有问题即get请求已经解决,接下来主要处理表单post请求

        

       4、处理登录post请求

    步骤:获取请求数据→查询数据库→发送响应

        

         首先获取表单数据,接下来链接数据库查询,因为之前已经加载过了用户数据设计文档

        

         所以接下来通过User操作即可

        

    注意:
        1、可以在读取失败时直接将错误信息发送回去,通过error自带的属性,即error.message属性。此时客户端在开发时,便可以看到详细报错信息
        2、因为是异步请求,服务端无法重定向到首页,所以需要发送成功响应,自定义状态码
        3、用户存在,登录成功,通过Session记录登录状态(稍后添加)

        测试如下

        

         点击确定后便会重定向到首页,接下来做下session登录状态存储。

      

    (16)通过session保存登录状态

       详见文章node通过session保存登录状态.

    (17)处理用户退出功能

      接下里编写退出功能,即点击退出按钮时进行用户退出操作

      

       

       接下来编写路由

      

    注意:a链接默认为同步请求,因为点击链接时,浏览器便会刷新。
      因为是同步请求,所以可以使用服务端重定向。注意:之前所讲,ajax异步请求的重定向,无法在服务端操作。

      

      

       

    (18)小结

      

       

       

       

    (19)总结

      

       

    .

  • 相关阅读:
    擅用伪元素::before(:before)和::after(:after)
    CSS清除浮动float
    javascript:void(0) 含义
    js运算符的优先级
    js的Array的sort()排序方法
    js将字符串转化为数字
    mvc:一
    六:使用注解整合开发
    五、整合struts2和mybatis和spring
    08_动态sql
  • 原文地址:https://www.cnblogs.com/jianxian/p/12272415.html
Copyright © 2020-2023  润新知