nodejs koa留言板案例开发

包含功能
登录注册(不开放注册只是用固定的账号信息)
查看列表
查看详情
发布信息
编辑信息
删除信息
项目接口

npm init -y
npm install koa --save
npm istall koa-router --save (旧版本) 或者 npm install @koa/router --save (新版本)
npm install bluebird --save
npm install koa-ejs --save
npm install koa-bodyparser --save

执行完毕之后 ,使用vscode 打开项目文件夹,继续往里面添加对应的文件目录和文件
在这里插入图片描述
authenticate.js

//认证中间件
module.exports = async function (ctx,next) {const logined = ctx.cookies.get('logined',{signed: true});ctx.state.logined = !!logined;await next();
}

路由开发
routes/post.js

const Router = require('koa-router');
const postService = require('../services/post');
const router = new Router();//发布表单页面
router.get('/publish', async (ctx) => {await ctx.render('publish');
});//发布处理
router.post('/publish', async (ctx) => {const data = ctx.body;if (!data.title || !data.content) {ctx.throw(500, '缺失必填参数');}const item = postService.publish(data.title, data.content);ctx.redirect(`/post/${item.id}`);
});//详情页面
router.get('/post/:postId', async (ctx) => {const post = postService.show(ctx.params.postId);if (!post) {ctx.throw(404, '消息记录不存在');}await ctx.render('post', { post: post });
});//编辑表单页面
router.get('/update/:postId',async (ctx)=>{const post = postService.show(ctx.params.postId); if (!post) {ctx.throw(404, '消息记录不存在');}await ctx.render('post', { post: post });
});//编辑处理
router.post('/update/:postId',async (ctx)=>{const data = ctx.body;if (!data.title || !data.content) {ctx.throw(500, '缺失必填参数');}const postId = ctx.params.postId;postService.update(postId,data.title,data.content);ctx.redirect(`/post/${postId}`);
});//删除
router.get('delete/:postId',async (ctx)=>{postService.delete(ctx.params.postId);ctx.redirect('/');
});module.exports = router;

routes/site.js

const Router = require('koa-router');
const postService = require('../services/post');
const router = new Router();//网站首页
router.get('/', async (ctx)={const list = postService.list();await ctx.render('index',{list : list});
});module.exports = router;

routes/user.js

const Router = require('koa-router');
const userService = require('../services/user');
const router = new Router();//登陆页面
router.get('/login', async(ctx) = {await ctx.render('login');
});//登录处理
router.post('/login', async(ctx) = {const data = ctx.request.body;if(!data.userName || !data.password){ctx.throw(500, '用户名或密码缺失必填参数');
}
const logined = userService.login(data.userName, data.password);
if (!logined) {ctx.throw(500, '用户名或密码错误');
}
ctx.cookies.set('logined', 1, {signed: true,httpOnly: true
});
ctx.router('/', '登陆成功');
});//退出登录
router.get('/logout', (ctx) => {ctx.cookies.set('logined', 0, {signed: true,maxAge: -1});ctx.router('/', '退出登陆成功');
});```**服务层开发 
services/post.js**
```
const fs = require('fs');
const bluebird = require('bluebird');//Promise 化 fs 的api
bluebird.promisifyAll(fs);//文章数据
const posts = [];
//文章ID
let postId = 1;//发表文章
exports.publish = function(title,content){const item = {id: postId++,title: title,content: content,time: (new Date()).toLocaleDateString()};posts.push(item);return item;
}//查看文章
exports.show = function(id){id = Number(id);for(const post of posts){if(post.id === id){return post;}}return null;
}//编辑文章
exports.update =function(id,title,content){id = Number(id);posts.forEach((post)=>{if(post.id === id){post.title = title;post.content = content;}});
}//删除文章
exports.delete = function (id){id = Number(id);let index = -1;posts.forEach((post)=>{if(post.id === id){index = id;}});if(index > -1){posts.slice(index,1)}
}exports.list = function(){return posts.map(item => item);
}```**serivce/user.js**```
const user = {liuyifei: 'password'
};//登录
exports.login = function(userName,password){if(user[userName] === undefined){return false;}return user[userName]  === password;
};
```=======================================================
**前端模板:**
**index.ejs**
```
<h1>文章显示列表</h1>
<% if(list.length === 0){ %>
<p>文章显示列表</p>
<% }else{ %>
<table><tr><th>id</th><th>标题</th><th>发布时间</th><% if(logined){ %><th>操作</th><% } %>  </tr><% list.forEach(post => { %><td><%= post.id %></td> <td><a href="/post/<%= post.id %>"><%= post.title  %></a></td> <td><%= post.time %></td> <% if(logined){ %><th><a href="/update/<%= post.id %>">编辑</a></th><th><a href="/delete/<%= post.id %>" onclick="return confirm('确认删除?')">删除</a></th><% } %><% }) %>
</table>
<% } %>    
```**login.ejs**
```
<form action="/login" method="post" enctype="application/x-www-form-urlencoded"><fieldset><legend>登录</legend><div><label for="userName">账号</label><input type="text" name="userName" id="userName" required /></div><div><label for="userName">密码</label><input type="password" name="password" id="password" required /></div>  <div><button type="submit">登录</button></div>    </fieldset>
</form>
```
**main.ejs**
```
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>首页</title>
</head><body><% if(logined) { %><a href="/">首页</a><a href="/publish">发表文章</a><a href="/logout">退出登录</a><% }else{%><a href="/login">退出登录</a><% } %><%- body  %></body>
</html>
```
**post.ejs**
```
<div><h1><%= post.title  %></h1> <time>发布时间:<%= post.time %></time>
<hr><div><%= post.content  %></div>
</div>
```
**publish.ejs**```
<form action="/publish" method="post" enctype="application/x-www-form-urlencoded"><fieldset><legend>发表文章</legend><div><label for="title">标题</label><input type="text" name="title" id="title" required></div><div><label for="content">内容</label><textarea name="content" id="content" required></textarea></div><div><button type="submit">发布</button><button type="reset">重置</button></div></fieldset>
</form>
```****update.ejs****
```
<form action="/update/<%=post.id  %>" method="post" enctype="application/x-www-form-urlencoded"><fieldset><legend>编辑文章</legend><div><label for="title">标题</label><input type="text" name="title" id="title" value="<%= post.title  %>" required></div><div><label for="content">内容</label><textarea name="content" id="content"  required ><%= post.content  %></textarea></div><div><button type="submit">发布</button><button type="reset">重置</button></div></fieldset></fieldset>
</form>
```
**index.js : 项目的入口文件,负责挂载中间件,路由,应用配置以及启动服务器**```
const Koa = require('koa');
const render = reuire('koa-ejs');
const bodyParser = require('koa-bodyParser');
//认证组件
const authenticate = require('./middlewares/authenticate');//路由
const siteRoute = require('./routes/site');
const userRoute = require('./routes/user');
const postRoute = require('./routes/post');const app = new Koa(); //定义服务
app.keys = ['wusoddn09Wa'];  //定义认证使用的key//挂载中间件
app.use(bodyParser());//关联使用模版
render(app,{root: './templates',layout: 'main',viewExt: 'ejs'}
);//挂载路由
app.use(siteRoute.routes()).use(siteRoute.allowedMethods());
app.use(userRoute.routes()).use(userRoute.allowedMethods());
app.use(postRoute.routes()).use(postRoute.allowedMethods());app.listen(8080,()=>{console.log(server start up on port: 8080);
});```

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/96660.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/96660.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4+ 图论高级算法

强连通分量 基础概念 强连通&#xff1a;在有向图 GGG 中&#xff0c;如果两个点 uuu 和 vvv 是互相可达的&#xff0c;即从 uuu 出发可以到达 vvv , 从 vvv 也可以到达 uuu , 则称 uuu 和 vvv 是强连通的。如果 GGG 中任意两个点都是互相可达的&#xff0c;则称 GGG 是强连通图…

从罗永浩访谈李想中学习现代家庭教育智慧

引言 在这个信息爆炸的时代&#xff0c;每个父母都在寻找培养孩子的最佳方式。在罗永浩与理想汽车创始人李想的深度访谈中&#xff0c;我们看到了一个成功企业家童年成长的真实样本。李想的成长经历为现代家庭教育提供了许多值得深思的启示。 一、正义感与乐观精神的种子 李想回…

AI实现超级客户端打印 支持APP 网页 小程序 调用本地客户端打印

核心思路都是&#xff1a;需要一个安装在用户电脑上的“中间人”程序&#xff08;本地客户端&#xff09;来接管打印任务&#xff0c;然后通过某种通信方式命令这个客户端进行打印。下面我将分平台详细阐述各种实现思路、优缺点和适用场景。一、核心思路与公共组件&#xff1a;…

Java集合(Collection、Map、转换)

✅ 推荐使用 ❌ 已过时 1. Collection Collection 是集合框架的根接口之一&#xff0c;它是所有单列集合&#xff08;如 List、Set、Queue 等&#xff09;的公共父接口。Collection 接口定义了集合的基本操作&#xff0c;比如添加、删除、遍历等。 Collection ├── List │ …

全国网络安全知识竞赛有哪些

全国范围内有多种类型的网络安全知识竞赛&#xff0c;涵盖国家级、行业级、高校、青少年和企业等多个维度。以下是主要的网络安全知识竞赛分类及详细介绍&#xff1a;一、国家级网络安全竞赛"强网杯"全国网络安全挑战赛主办单位&#xff1a;中央网信办、河南省人民政…

系统架构设计师备考第1天——系统架构概述

一、架构本质与角色定位架构 系统的骨架 ✅ 核心作用&#xff1a; 决定系统的健壮性、生命周期、扩展性衔接需求与实现&#xff0c;保障早期质量 &#x1f468;&#x1f4bb; 架构师核心能力&#xff1a;能力维度具体要求技术掌控力精通基础技术&#xff0c;洞悉局部瓶颈决策设…

c#实现鼠标mousemove事件抽稀,避免大数据阻塞网络

这个封装类可以独立于具体的网络传输逻辑&#xff0c;为任何需要减少鼠标移动数据量的应用提供灵敏度和数据量优化。 核心优化功能 1. 灵敏度调整 // 减少微小移动的数据发送 (2, 1) 0.5 → (1, 0) // 忽略微小移动2. 移动累积 // 累积多次小移动&#xff0c;批量发送 (1, 0) …

机器学习 [白板推导](十三)[条件随机场]

​ 17. 条件随机场&#xff08;Conditional Random Field&#xff0c;CRF&#xff09; 17.1. 背景 机器学习分类模型中&#xff0c;有硬分类和软分类两种主流思想&#xff0c;其中硬分类模型有支持向量机SVM&#xff08;最大化几何间隔&#xff09;、感知机PLA&#xff08;误…

调味品生产过程优化中Ethernet/IP转ProfiNet协议下施耐德 PLC 与欧姆龙 PLC 的关键通信协同案例

案例背景在食品饮料行业&#xff0c;生产过程的精准控制对于保证产品质量和安全至关重要。某知名食品饮料企业的生产线上&#xff0c;前处理、灌装和包装环节采用了基于 ProfiNet 主站的施耐德 M340 系列 PLC 进行控制&#xff0c;以确保生产过程的稳定性和精确性。而原料仓储和…

Elasticsearch vs 单表LIKE查询性能对比

关键因素影响 1、索引结构&#xff1a; .Elasticsearch使用倒排索引&#xff0c;特别适合文本搜索 .传统数据库即使有索引&#xff0c;对LIKE %keyword%这种模式也无法有效利用 2、查询复杂度&#xff1a; .简单查询&#xff1a;ES快5-10倍 .复杂组合查询&#xff1a;ES可能快1…

如何通过WordPress联盟营销获取潜在客户

您是否经营着一个销售周期较长的业务&#xff1f; 那么你就会知道&#xff0c;从首次访问者那里获得立即销售的机会是很少见的。 当然&#xff0c;您的潜在客户在进行重大投资之前需要时间进行研究、比较各种方案并建立信任。这时&#xff0c;联盟营销线索挖掘就成为您的秘密…

git实战(8)git高阶命令分析【结合使用场景】

以下是 Git 高阶命令分享&#xff0c;涵盖高效协作、历史重构、问题排查等场景&#xff0c;助你成为 Git 高手&#xff1a; 一、历史重构与清理 1. 交互式变基&#xff08;改写历史&#xff09; git rebase -i HEAD~3 # 修改最近3次提交操作选项&#xff1a; reword&#xff1…

生成一个竖直放置的div,宽度是350px,上面是标题固定高度50px,下面是自适应高度的div,且有滚动条

<!-- 我要生成一个竖直放置的div&#xff0c;宽度是350px&#xff0c;上面是标题固定高度50px&#xff0c;下面是自适应高度的div&#xff0c;且有滚动条。 --><style>html,body{/* height:100vh; */margin:10px; padding:10px;} </style><div style"…

题解:P13754 【MX-X17-T3】Distraction_逆序对_前缀和_Ad-hoc_算法竞赛C++

Beginning 这道题思维难度很大&#xff0c;有两个难点其实都不好解决&#xff0c;但因为其代码太过弱智所以只是绿题。 本题解详细地分析了做题时的历程与思路&#xff0c;所以希望大家可以仔细地完整阅读。 Analysis 首先先大体观察一下题目的性质&#xff1a;nnn 是排列&…

Android Studio下载gradle文件很慢的捷径之路

小伙伴们是不是也经常遇到导入新的项目时&#xff0c;AS一直卡在gradle的下载中。下面介绍一种简单暴力的方式来处理这个问题。 首先我们到gradle的官网下载自己想要的gradle版本。我这里以gradle7.5为例。点击下载gradle-7.5-bin.zip的压缩包。下载完成后无需解压。直接到C:\U…

【C++】全局变量/静态变量的初始化时机

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、全局变量下断点调试1. int a 10; —— 不能卡住断点2. static int b; —— 不能卡住断点3. MyClass c; —— 可以卡住断点4. static MyClass d; —— 可以卡住断…

水体反光 + 遮挡难题破解!陌讯多模态融合算法在智慧水务的实测优化

一、智慧水务行业检测痛点&#xff08;数据支撑 场景难点&#xff09; 根据《2023 年中国智慧水务发展报告》&#xff0c;当前水务监控系统在核心业务场景中面临两大效率瓶颈&#xff0c;直接影响水厂运维与供水安全&#xff1a; 高误报率导致运维资源浪费&#xff1a;水厂沉…

C++的指针和引用:

目录 引用&#xff1a; 注意&#xff1a; 左值引用和右值引用&#xff1a; 左值引用&#xff1a; 右值引用&#xff1a; 指针&#xff1a; 指针与引用的区别&#xff1a; 引用&#xff1a; 在C中&#xff0c;‌引用‌是一种为已存在变量创建别名的机制&#xff0c;它允…

图像处理中的伪影

目录 一、块效应伪影 / 块状伪影 二、 去除块状伪影 三、振铃伪影 一、块效应伪影 / 块状伪影 块状伪影(Blocking Artefacts)是对经过变换编码的图像进行重建时&#xff0c;图像中可能会出现压缩过程产生的可见伪影。基于块的变换编码中&#xff0c;一种常见伪影是 “块效应…

Java:对象的浅拷贝与深拷贝

目录 一、概念 二、实现方式 2.1 浅拷贝&#xff08;不推荐&#xff09; 2.2 深拷贝 2.2.1 方法一&#xff1a;重写 clone() 方法并递归克隆&#xff08;常用&#xff09; 2.2.2 方法二&#xff1a;通过序列化实现&#xff08;更强大&#xff0c;但更重&#xff09; 2.2…