基于 Express 与 Mongodb 的简易 实现一个多人 blog
项目参考:
N-blog: github.com/nswbmw/N-bl…
感谢作者大大详尽的指导,后端基本用的作者原始的架构
关于 fetchAPI, express 的原理没有深入了解,总体做了点搬砖的活
项目地址:
SimpleBlog: github.com/ShiroCheng/…
该项目已布在公网服务器上,demo地址:http://120.78.134.26
页面演示:
- 主页:
- 特定文章页:
- 发布文章页:
- 电影页:
使用方法:
环境配置:预装 MongoDB, Node.js
mkdir mongodb/data
mongod --dbpath=mongodb/data
git clone https://github.com/Ubilabs-NicholasCheng/SimpleBlog.git
cd SimpleBlog
npm i
vim config/default.js #修改端口 80->3000
node index.js
之后,访问 localhost:3000
项目目录结构:
lib
: 定义实体的数据结构models
: 操作数据库的文件public
: 静态文件,如样式、图片,包括用户上传的头像等routes
: 存放路由文件views
: 用于渲染的视图文件index.js
: 程序主文件package.json
: 项目名、描述、作者、依赖等等信息config
: 项目的配置信息,服务器端口,连接的数据库端口等遵循 MVC 的开发模式
前端组件库
Materilazie + GoogleIcons
: Material Design 风格的组件库与 Google 图标github-markdown-css
: 添加 github markdown 风格样式highlight.js
: 代码语法高亮simpleMDE
: markdown 的样式支持jquery
: 实现动画等功能materialize.min.js
: materialize 组件的js库
后端依赖模块
express
: web 框架express-session
: session 中间件connect-mongo
: 将 session 存储于 mongodb,结合 express-session 使用connect-flash
: 页面通知的中间件,基于 session 实现ejs
: 模板express-formidable
: 接收表单及文件上传的中间件config-lite
: 读取配置文件marked
: markdown 解析moment
: 时间格式化mongolass
: mongodb 驱动objectid-to-timestamp
: 根据 ObjectId 生成时间戳sha1
: sha1 加密,用于密码加密winston
: 日志express-winston
: express 的 winston 日志中间件
主要功能
- 多用户注册登录
- 发表、修改、删除文章
- 发表、删除评论
- 添加视频
实现方法
- 服务器后端框架:express,使用express 控制路由,动态渲染特定界面
- 数据库驱动:Mongolass,服务器与数据库交互的中间件
- 模板引擎:ejs,动态渲染前端页面
以登陆后的用户创建 movies 为实例:
定义 Movie 的 schema:
// lib/mongo.js
const Mongolass = require('mongolass')
const mongolass = new Mongolass()/********* Movie Schema **********/
exports.Movie = mongolass.model('Movie', {title:{type: 'string',required: true},src:{type: 'string',required: true}
})// 建立索引
exports.Movie.index({postId:1,_id: 1}).exec()
Movie 这个 model 中定义的方法,加载所有电影,删除与获取特定的电影:
(Mongolass 这个驱动的方法与mongodb的数据库api一致,使用起来很直观)
// model/movies.js
const Movies = require('../lib/mongo').Moviemodule.exports = {create: function create (movie){return Movies.create(movie).exec()},// 通过电影 id 获取一部电影getMovieById: function getMovieById(movieId){return Movies.findOne({_id: movieId}).exec()},// 通过电影 id 删除一部电影delMovieById: function (movieId){return Movies.deleteOne({_id: movieId}).exec()},//找到所有的电影getMovies: function (){return Movies.find({}).exec()}
}
定义表单的方法为 post,input 的 name 为属性名。
// views/createMovies.ejs
<form class="col s12 m12 " method="POST">// more code here <input name="title" id="title" type="text" class="validate"><input name="src" id="src" type="text" class="validate" >// more code here
</form>
express 的路由中提供了处理请求的方法,input 的 value 将挂载在 req.fileds.name 这一属性下:
使用 MovieModel 的 create方法,在数据库对应的表中插入这一条用户新创建的数据,若该表不存在则会创建该表。
// routes/movies.js
// 创建电影页
router.post('/create', function(req, res, next){const movieId = req.fields.movieIdconst title = req.fields.titleconst src = req.fields.src// 校验参数try {if (!src.length) {throw new Error('Please write movie src!')}} catch (e) {req.flash('error', e.message)return res.redirect('back')}const movie = {movieId: movieId,title: title,src: src}MovieModel.create(movie).then(function(){req.flash('success', 'create movie successfully!')// 创建成功后跳转到上一页res.redirect('/movies')}).catch(next)})
同时引入了 checkLogin 方法,判断用户是否登陆,登陆后的用户才有权限创建电影:
// middlewares/checkLogin.js
module.exports = {checkLogin: function checkLogin(req, res, next){if (!req.session.user) {//设置当前的错误为未登录req.flash('error', '未登录')return res.redirect('/signIn')}next()},checkNotLogin: function checkNotLogin(req, res, next){if (req.session.user) {req.flash('error', '已登录')return res.redirect('back') //若已登录返回原页面}next()}
}
使用 MovieModel 中定义的 getMovies() 方法,查询到 movies 表下的所有记录,使用res.render() 方法渲染ejs模板,并传入这些查询到的记录。
// routes/movies.js
// 显示电影页
router.get('/', function(req, res, next){MovieModel.getMovies().then(function (movies){res.render('movies', {movies: movies})}).catch(next)
})
前端的 ejs 模板获取到服务器响应传入的多条记录,使用 forEach方法将其依次渲染:
(components/movies-content.ejs 作为组件,movies.ejs 使用include方法渲染多个 movies-content.ejs组件 )
// views/components/movies-content.ejs
<label><h5 class="white-text center-align" style="margin-top: 230px;"><%= movie.title %></h5></label><div class="responsive-video center-align" controls><iframe width="853" height="480" src="<%= movie.src %>" frameborder="0" allowfullscreen> </iframe></div>
// views/movies.ejs
<%- include('header') %><% movies.forEach(function (movie) { %><%- include('components/movie-content', { movie: movie }) %><% }) %>
<%- include('footer') %>
这样,就完成了一个简单的 用户提交表单 -> 服务端存储数据到数据库 -> 服务端重渲染视图 的前后端交互流程 。
项目的设计还涉及到用户密码的hash加密,时间日期的格式化,日志的保存等,配置文件的更改及代码风格等,但简单的流程就如上所示。
TO DO
- 增加用户文章的分类与标签功能
- 增加文章的分页显示功能
- 增加用户的文章收藏功能
- 增加电影的分类与标签功能
- 增加用户的电影收藏功能
基于 Express 与 Mongodb 的简易 实现一个多人 blog相关推荐
- 天鼎:一个技术人在世界读书日的遐想
图片来源pexels.com 基于CC0协议 01 天鼎:一个技术人在世界读书日的遐想 写在世界读书日 " 我是一个老派技术渣,大学学习谭浩强老师的C语言,毕业后做嵌入式开发,由于工作变动学 ...
- [译]简单得不得了的教程-一步一步用 NODE.JS, EXPRESS, JADE, MONGODB 搭建一个网站
原文: http://cwbuecheler.com/web/tutorials/2013/node-express-mongo/ 原文的源代码在此 太多的教程教你些一个Hello, World!了, ...
- 一个迷你的 Node.js 基于 Express 的 MVR 模式的 API工程 的分析
1. 工程说明 该工程是基于 Express 库,编写的一个 API 查询返回的一个微型应用. API Resource 就是把 API 的内容当做网络资源去处理.工程中的路由访问也是返回 API 内 ...
- 详细记录基于vue+nodejs+mongodb构建的商城学习(四)基于项目的node.js开发后端的学习与梳理总结...
前置: 本系列文章是一个本人边学习边梳理的学习笔记,俗话说好脑袋不如烂笔头,再好的记忆力时间长了也会有细节忘记,本项目选择的前端框架是vue,后端开发使用是node.js,数据库使用的是mongodb ...
- QuickMock:基于Express的快速mock平台
前言 感兴趣的话,可以star关注支持下,项目地址. 在日常的开发中,前端mock后端api数据,是实现前后端并行开发非常重要的一步.有了数据,才能更加真实反馈实际操作流程,交互效果才能更好的编码实现 ...
- 如何搭建html运行环境,搭建基于express框架运行环境的方法步骤
一.Express简介 Express提供了一个轻量级模块,把Node.js的http模块功能封装在一个简单易用的接口中.Express也扩展了http模块的功能,使你轻松处理服务器的路由.响应.co ...
- 如何使用Node.js,Express和MongoDB设置GraphQL服务器
by Leonardo Maldonado 莱昂纳多·马尔多纳多(Leonardo Maldonado) 如何使用Node.js,Express和MongoDB设置GraphQL服务器 (How to ...
- 使用Express和MongoDB构建简单的CRUD应用程序
by Zell Liew 由Zell Liew 使用Express和MongoDB构建简单的CRUD应用程序 (Building a Simple CRUD Application with Expr ...
- 使用Express和MongoDB构建CRUD应用程序-第2部分
by Zell Liew 由Zell Liew 使用Express和MongoDB构建CRUD应用程序-第2部分 (Building a CRUD Application with Express a ...
最新文章
- netcore读取json文件_.net core读取json格式的配置文件
- fastjson 对象和json互转
- [日常] DNS的迭代查询过程
- listrecord根据某个属性去重_天刀手游琅纹搭配攻略,全门派全装备最细节提属性教学...
- linux的poll_wait函数,select() 与 poll()两个函数接口的作用
- 38.django的路由系统
- jetson nano的USB转232 DB9串口线选购
- 声道测试音频_嵌入式平台上的自动音频接口测试
- 熊出没之伐木机器人_盘点熊出没中李老板的五大伐木工,光头强无人能代替
- 支付宝登录应用授权,后端拼接 authinfo返回app,app进行支付宝调用获取auth_code(com.alipay.account.auth)
- 秦皇岛自驾三日游攻略
- Tesseract文字训练,以及样本生成
- 服务器硬盘上面的12gb和6gb的区别,4GB和6GB有什么区别?看完千万别买错,已有多人后悔!...
- 亚马逊echo中国使用_如何设置和配置您的Amazon Echo
- 第三方支付(微信支付)支付流程分析
- 初识阿里云(云计算)--发展历程和技术架构、地域和可用区
- openGauss亮相ICDE2021,分享数据库的AI晋级之路
- Java架构-微信交流群
- composer安装阿里大鱼扩展
- mousemove事件,鼠标移动过快时,无法全部响应