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);
});

```
相关推荐
竹林8181 小时前
用 wagmi v2 + viem 监听链上事件,我踩了三天坑终于搞懂了实时日志与历史补全
javascript
Momo__1 小时前
VueUse createReusableTemplate —— 单文件组件内的模板复用神器
前端·vue.js
只一1 小时前
😭从回调地狱到 async/await:一文打通 Ajax 与 JS 异步编程
javascript
程序员小富1 小时前
我开源了一个开发者专属的智能 JSON 工具,得到了媳妇高度认可
前端·vue.js·后端
小小小小宇1 小时前
程序员如何给 LLM 装工具以及看懂推理过程
前端
写代码的皮筏艇1 小时前
React中的forwardRef
前端·react.js·面试
槑有老呆1 小时前
花三个月工资请了个 AI 程序员,结果它连青岛啤酒股价都查不了
前端
风骏时光牛马1 小时前
Verilog开发常见问题汇总解析
前端
子兮曰1 小时前
AI Coding Method Map:一张图看懂 AI 编程的完整链路
前端·人工智能·后端