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
英文地址,請注明出處:http://en.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…