博客项目

    科技2022-08-06  104

    初始化

    1、建立文件夹 public:静态资源 model:数据库操作 route:路由 views:模板 2、初始化项目描述文件 npm init -y

    3、下载项目所需第三方模块 npm install express mongoose art-template express-art-template

    4、创建网站服务器 app.js

    //获取express模块 const express = require("express"); //创建网站服务器 const app = express(); // 监听端口 app.listen(80); console.log("服务器启动成功,请访问localhost");

    5、构建模块化路由 route/admin.js

    //获取express模块 const express = require("express"); // 获取路由对象 const admin = express.Router(); // 挂载路由 home.get("/", (req, res) => { res.send("欢迎来到博客登录页") }); //导出admin module.exports = admin;

    route/home.js

    //获取express模块 const express = require("express"); // 获取路由对象 const home = express.Router(); // 挂载路由 home.get("/", (req, res) => { res.send("欢迎来到博客首页") }); //导出home module.exports = home;

    app.js

    //获取路由 const home = require("./route/home"); const admin = require("./route/admin"); //匹配路由 app.use("/home", home); app.use("/admin", admin);

    6、构建管理页面模板 app.js

    //获取path模块 const path = require("path"); //开放静态资源访问 app.use(express.static(path.join(__dirname, "public"))); //指定渲染哪种后缀文件,用哪种模板引擎 app.engine("art", require("express-art-template")); //指定模板根目录 app.set("views", path.join(__dirname, "views")); //设置渲染文件默认后缀 app.set("view engine", "art");

    admin.js

    const express = require("express"); // 获取路由对象 const admin = express.Router(); // 挂载路由 admin.get("/login", (req, res) => { res.render("admin/login") }); admin.get("/user", (req, res) => { res.render("admin/user") }); //导出admin module.exports = admin;

    public: views: 骨架文件: 用block标签进行挖坑 每个模板包裹block标签填坑 公共文件: 使用extend 路径 进行继承 使用include 路径 进行导入

    登录

    1、创建用户集合,初始化用户 连接数据库 model/connect.js

    // 导入mongoose模块 const mongoose = require("mongoose"); //连接数据库 mongoose.connect("mongodb://localhost/blog", { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => console.log("数据库连接成功")) .catch((err) => console.log("数据库连接失败", err));

    app.js

    //连接数据库 require("./model/connect");

    创建用户集合 model/user.js

    // 导入mongoose模块 const mongoose = require("mongoose"); //创建用户集合规则 const userSchema = new mongoose.Schema({ username: { type: String, required: true, minlength: 2, maxlength: 20 }, email: { type: String, unique: true }, password: { type: String, required: true }, role: { type: String, required: true }, state: { type: Number, default: 0 } }) //创建用户集合规则 const User = mongoose.model("User", userSchema); //导出 module.exports = { User }

    初始化用户 2、为登录表单项设置请求地址,请求方式以及单项name属性 3、用户点击登录按钮时,客户端验证用户是否填写了登录表单 4、如果其中一项没有输入,阻止表单提交 login.art

    <script type="text/javascript"> // 为表单设置提交事件 $("#loginForm").on("submit", function() { var result = serializeToJson($(this)); if (result.email.trim().length == 0) { alert("请输入邮箱地址"); return false; } if (result.password.trim().length == 0) { alert("请输入密码"); return false; } }) </script>

    5、服务端接收请求参数,验证用户是否填写了登录表单 6、如果其中一项没有输入,为客户端做出相应,阻止程序向下执行 admin.js

    // 获取提交的表单数据的值 const { email, password } = req.body; if (email.trim().length == 0 || password.trim().length == 0) { return res.status(400).render("admin/error", { msg: "邮箱地址或密码错误" }) }

    7、根据邮箱地址查询用户信息 8、如果用户不存在,为客户端做出响应,阻止程序向下执行 9、如果用户存在,将用户名的密码进行比对 10、比对成功,用户登录成功 11、比对失败,用户登录失败 admin.js

    //登录提交 admin.post("/login", async(req, res) => { // 获取提交的表单数据的值 const { email, password } = req.body; if (email.trim().length == 0 || password.trim().length == 0) { return res.status(400).render("admin/error", { msg: "邮箱地址或密码错误" }) } //获取email条件下的用户信息 //如果有,则user为对象 // 如果无,则user为空 let user = await User.findOne({ email }); if (user) { if (password == user.password) { res.send("登陆成功") } else { return res.status(400).render("admin/error", { msg: "邮箱地址或密码错误" }) } } else { return res.status(400).render("admin/error", { msg: "邮箱地址或密码错误" }) } })

    密码加密

    bcrypt依赖环境: 1、python 2.x 2、node-gyp npm install -g node-gyp 3、windows-build-tools npm install --global --production windows -build -tools 语法:

    const bcrypt = require("bcrypt"); let salt = await bcrypt.genSalt(10); let pass = await bcrypt.hash("明文密码",salt)

    cookies与session

    cookie:浏览器在电脑硬盘开辟的一块供服务端存储数据的空间 session:一个对象,存储在服务器端的内存中,在session对象也可以存储多条数据,每一条数据都有一个sessionid做为唯一标识 命令:npm install express-session 语法: app.js

    //获取session模块 const session = require("express-session"); //配置express-session app.use(session({ resave: false, //添加 resave 选项 saveUninitialized: true, //添加 saveUninitialized 选项 secret: "secret key" }));

    admin.js

    if (user) { if (password == user.password) { req.session.username = user.username; res.send("登陆成功") } admin.get("/user", (req, res) => { res.render("admin/user", { msg: req.session.username }) });

    重定向页面

    res.redirect

    退出功能

    admin.get("/logout", (req, res) => { req.session.destroy(function() { res.clearCookie("connect,sid"); res.redirect("/admin/login") }) });

    新增用户

    1、为用户列表页的新增用户按钮添加链接 2、添加一个链接对应的路由,在路由处理函数中渲染新增用户模板 3、为新增用户表单指定请求地址,请求方式,为表单添加name属性 4、增加实现添加用户的功能路由 5、接收客户端传递过来的请求参数 6、对请求参数的格式进行验证 7、验证当前要注册的邮箱地址是否已经注册过 8、对密码进行加密处理 9、将用户信息添加到数据库中 10、重定向到用户列表页面

    第三方模块Joi

    JavaScript对象的规则描述语言和验证器

    数据分页

    核心: 当前页,用户通过点击上一页或者下一页或者页码产生,客户端通过get参数方式传递到服务器端 总页数,根据总页数判断当前页是否为最后一页,根据判断结果做响应操作 总页数:Math.ceil(总数据条数 / 每页显示数据条数) limit(2) // limit 限制查询数量 传入每页显示的数据数量 skip(1) // skip 跳过多少条数据 传入显示数据的开始位置 数据开始查询位置=(当前页-1)* 每页显示的数据条数

    admin.get("/user", async(req, res) => { req.app.locals.currentLink = 'user'; //当前页 let page = req.query.page || 1; //每一页显示条数 let pageSize = 10; //查询用户数据总数 let count = await User.countDocuments(); //总页数 let total = Math.ceil(count / pageSize); //查询开始位置 let start = (page - 1) * pageSize; //查询数据 let users = await User.find().limit(pageSize).skip(start); res.render("admin/user", { users, page, total }) });

    用户信息修改

    将要修改的用户ID传递到服务器端建立用户信息修改功能对应的路由接收客户端表单传递过来的请求参数根据id查询用户信息,并将客户端传递过来的密码和数据库中的密码进行比对如果比对失败,对客户端做出响应如果密码对比成功,将用户信息更新到数据库中 admin.post("/user-modify", async(req, res) => { req.app.locals.currentLink = 'user'; const { username, email, role, state } = req.body; const id = req.query.id; const url = "/admin/user-edit?id=" + id; let user = await User.findOne({ id: id }); if (req.body.password == user.password) { await User.updateOne({ id: id }, { username: username, email: email, role: role, state: state }) res.redirect("/admin/user"); } else { res.send("密码不一致") } })

    用户信息删除

    在确认删除框中添加隐藏域用以存储要删除用户的ID值为删除按钮添自定义属性用以存储要删除用户的ID值为删除按钮添加点击事件,在点击事件处理函数中获取自定义属性中存储的ID值并将ID值存储在表单的隐藏域中为删除表单添加提交地址以及提交方式在服务器端建立删除功能路由接收客户端传递过来的id参数根据id删除用户 admin.get("/delete", async(req, res) => { req.app.locals.currentLink = 'user'; await User.findOneAndDelete({ _id: req.query.id }); res.redirect("/admin/user") })

    文章管理

    formidable

    解析表单,支持get、post请求、文件上传

    数据分页

    mongoose-sex-page

    第三方模块config

    自动匹配运行环境读取对应的配置信息 命令:npm install config 1、安装 2、项目根目录新建config文件夹 3、里面新建default.json,development.json,production.json 4、项目中导入模块 5、使用内部提供的get方法获取配置信息

    前端页面

    创建评论集合 判断用户是否登录,如果用户登录,再允许用户提交评论表单 在服务器端创建文章评论功能对应的路由 在路由请求处理函数中接收客户端传递过来的评论信息 将评论信息存储在评论集合中 将页面重定向回文章详情页面 在文章详情页面路由中获取文章评论信息并展示在页面中

    Processed: 0.016, SQL: 8