需要安装的模块
- body-parser 解析post请求
- cookies 读写cookie
- express 搭建服务器
- markdown Markdown语法解析生成器
- mongoose 操作Mongodb数据库
- swig 模板解析引擎
目录结构
- db 数据库存储目录
- models 数据库模型文件目录
- public 公共文件目录(css,js,img)
- routers 路由文件目录
- schemas 数据库结构文件
- views 模板视图文件目录
- app.js 启动文件
- package.json
app.js 文件
1.创建应用、监听端口
const app = express();
app.get('/',(req,res,next) => {
res.send("Hello World !");
});
app.listen(3000,(req,res,next) => {
console.log("app is running at port 3000");
});
2.配置应用模板
- 定义使用的模板引擎 app.engine('html',swig.renderFile) 参数1:模板引擎的名称,同时也是模板文件的后缀 参数2:表示用于解析处理模板内容的方法
- 设置模板文件存放的目录 app.set('views','./views')
- 注册所使用的模板引擎 app.set('view engine','html')
3.用模板引擎去解析文件
/**
* 读取views目录下的指定文件,解析并返回给客户端
* 参数1:模板文件
* 参数2:给模板传递的参数
*/
res.render('index',{
title:'首页 ',
content: 'hello swig'
});
4.开发过程中需要取消模板缓存的限制
swig.setDefaults({
cache: false
});
app.set('view cache', false);
5.设置静态文件托管
// 当用户访问的是/public路径下的文件,那么直接返回
app.use('/public',express.static(__dirname + '/public'));
划分模块
- 前台模块
- 后台模块
- API模块
// 根据不同的功能划分模块
app.use('/',require('./routers/main'));
app.use('/admin',require('./routers/admin'));
app.use('/api',require('./routers/api'));
对于管理员模块 admin.js
var express = require('express');
var router = express.Router();
// 比如访问 /admin/user
router.get('/user',function(req,res,next) {
res.send('User');
});
module.exports = router;
前台路由 + 模板
main 模块
/ 首页
/view 内容页
api模块
/首页
/register 用户注册
/login 用户登录
/comment 评论获取
/comment/post 评论提交
后台(admin)路由+模板
首页
/ 后台首页
用户管理
/user 用户列表
分类管理
/category 分类列表
/category/add 分类添加
/category/edit 分类修改
/caterory/delete 分类删除
文章内容管理
/article nei内容列表
/article/add 内容添加
/article/edit 内容修改
/article/delete 内容删除
评论内容管理
/comment 评论列表
/comment/delete 评论删除
功能开发顺序
功能模块开发顺序
- 用户
- 栏目
- 内容
- 评论
编码顺序
- 通过Schema定义设计数据存储结构
- 功能逻辑
- 页面展示
连接数据库(mongoDB)
启动MongoDB服务端:
mongod --dbpath=G:\data\db --port=27017
启动服务设置数据库的存储地址以及端口
var mongoose = require('mongoose');
// 数据库链接
mongoose.connect("mongodb://localhost:27017/blog",(err) => {
if(err){
console.log("数据库连接失败");
}else{
console.log("数据库连接成功");
// 启动服务器,监听端口
app.listen(3000,(req,res,next) => {
console.log("app is running at port 3000");
});
}
});
定义数据表结构和模型
对于用户数据表(users.js)在schema文件夹下:
var mongoose = require('mongoose');
module.exports = new mongoose.Schema({
// 用户名
username:String,
// 密码
password:String
});
在models目录下创建user.js模型类
var mongoose = require('mongoose');
var userSchema = require('../schemas/users');
module.exports = mongoose.model('User',userSchema);
处理用户注册
前端通过ajax提交用户名和密码
url: /api/register
后端对前端提交(POST)的数据解析
var bodyParser = require('body-parser');
// bodyParser 配置
// 通过使用这一方法,可以为req对象添加一个body属性
app.use( bodyParser.urlencoded({extended:true}));
// 在api模块中:
// 1.可以定义一个中间件,来统一返回格式
var responseData;
router.use( function(req,res,next){ // path默认为'/',当访问该目录时这个中间件被调用
responseData = {
code:0,
message:''
};
next();
});
router.post('/register',(req,res,next) => {
console.log(req.body);
// 去判断用户名、密码是否合法
// 判断是否用户名已经被注册
// 通过 res.json(responseData) 给客户端返回json数据
// 查询数据库
User.findOne({ // 返回一个promise对象
username: username
}).then(function( userInfo ) {
if( userInfo ){ // 数据库中有该条记录
...
res.json(responseData);
return;
}
// 给数据库中添加该条信息
var user = new User({ username:username,password:password });
return user.save(); // 返回promise对象
}).then(function( newUserInfo ){
console.log(newUserInfo);
res.json(responseData); // 数据保存成功
});
});
cookies 模块的使用
全局(app.js)注册使用
// 设置cookie
// 只要客户端发送请求就会通过这个中间件
app.use((req, res, next) => {
req.cookies = new cookies(req, res);
/**
* 解析用户的cookies信息
* 查询数据库判断是否为管理员 isAdmin
* 注意:查询数据库是异步操作,next应该放在回调里边
*/
req.userInfo = {};
if (req.cookies.get("userInfo")) {
try {
req.userInfo = JSON.parse(req.cookies.get("userInfo"));
// 查询数据库判断是否为管理员
User.findById(req.userInfo._id).then(function (result) {
req.userInfo.isAdmin = Boolean(result.isAdmin);
next();
});
} catch (e) {
next();
}
} else {
next();
}
});
// 当用户登录或注册成功之后,可以为其设置cookies
req.cookies.set("userInfo",JSON.stringify({
_id:result._id,
username:result.username
}));
swig模板引擎
1.变量
{{ name }}
2.属性
{{ student.name }}
3.if判断
{ % if name === '郭靖' % }
hello 靖哥哥
{ % endif % }
4.for循环
// arr = [1, 2, 3]
{ % for key, val in arr % }
<p>{ { key } } -- { { val } }</p>
{ % endfor % }
5.set命令
用来设置一个变量,在当前上下文中复用
{% set foo = [0, 1, 2, 3, 4, 5] %}
{% extends 'layout.html' %} // 继承某一个HTML模板
{% include 'page.html' %} // 包含一个模板到当前位置
{% block main %} xxx {% endblock %} //重写某一区块
6.autoescape 自动编码
当想在某个div中显示后端生成的HTML代码,模板渲染时会自动编码,
以字符串的形式显示。通过以下方式,可以避免这个情况:
<div id="article-content" class="content">
{% autoescape false %}
{{ data.article_content_html }}
{% endautoescape %}
</div>
用户管理和分页
CRUD用户数据
const User = require('../models/user');
// 查询所有的用户数据
User.find().then(function(users){
});
// 根据某一字段查询数据
User.findOne({
username:username
}).then(function(result){
});
// 根据用户ID查询数据
User.findById(id).then(function(user){
});
// 根据ID删除数据
User.remove({
_id: id
}).then(function(){
});
// 修改数据
User.update({
_id: id
},{
username: name
}).then(function(){
});
数据分页管理
两个重要方法
limit(Number): 限制获取的数据条数
skip(Number): 忽略数据的条数 前number条
忽略条数:(当前页 - 1) * 每页显示的条数
// 接收传过来的page
let query_page = Number(req.query.page) || 1;
query_page = Math.max(query_page, 1); // 限制最小为1
query_page = Math.min(Math.ceil(count / limit), query_page); // 限制最大值 count/limit向上取整
var cur_page = query_page; // 当前页
var limit = 10; // 每页显示的条数
var skip = (cur_page - 1) * limit; //忽略的条数
User.find().limit(limit).skip(skip).then(function(users){
...
// 将当前页 page 传给页面
// 将最大页码 maxPage 传给页面
});
文章的表结构
// 对于content.js
var mongoose = require('mongoose');
var contentSch = require('../schemas/contentSch');
module.exports = mongoose.model('Content',contentSch);
// contentSch.js
module.exports = new mongoose.Schema({
// 关联字段 - 分类的id
category:{
// 类型
type:mongoose.Schema.Types.ObjectId,
// 引用
ref:'Category'
},
// 内容标题
title: String,
// 简介
description:{
type: String,
default: ''
},
// 内容
content:{
type:String,
default:''
}
});
// 文章查询时关联category字段
Content.find().populate('category').then(contents => {
// 那么通过这样的方式,我们就可以找到Content表中的
// 关联信息 content.category.category_name
});
MarkDown语法高亮
在HTML中直接使用
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"> <script src="/UploadFiles/2021-04-02/highlight.min.js">node环境中使用
// 在模板页面引入默认样式 <!--语法高亮--> <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css"> const marked = require('marked'); const hljs = require('highlight.js'); // marked相关配置 marked.setOptions({ renderer: new marked.Renderer(), gfm: true, tables: true, breaks: false, pedantic: false, sanitize: true, smartLists: true, smartypants: false, highlight: function (code) { return hljs.highlightAuto(code).value; } }); // 对内容进行markdown语法转换 data.article_content_html = marked(article.content);使文本域支持Tab缩进
$('#bjw-content').on('keydown',function(e){ if(e.keyCode === 9){ // Tab键 var position = this.selectionStart + 2; // Tab === 俩空格 this.value = this.value.substr(0,this.selectionStart) + " " + this.value.substr(this.selectionStart); this.selectionStart = position; this.selectionEnd = position; this.focus(); e.preventDefault(); } });layer 弹框
// 显示弹框 function showDialog(text, icon, callback) { layer.open({ time: 1500, anim: 4, offset: 't', icon: icon, content: text, btn: false, title: false, closeBtn: 0, end: function () { callback && callback(); } }); });随机用户头像生成
// 引入对应的库 const crypto = require('crypto'); const identicon = require('identicon.js'); // 当用户注册时,根据用户的用户名生成随机头像 let hash = crypto.createHash('md5'); hash.update(username); let imgData = new identicon(hash.digest('hex').toString()); let imgUrl = 'data:/image/png;base64,'+imgData;orm表单提交的小问题
当使用form表单提交一些代码的时候,会出现浏览器拦截的现象,原因是:浏览器误以为客户进行xss攻击。所以呢解决这个问题也很简单,就是对提交的内容进行base64或者其他形式的编码,在服务器端进行解码,即可解决。
源码地址:https://github.com/bjw1234/blog
node,博客开发
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]