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

```
相关推荐
WebInfra31 分钟前
Rspack 1.5 发布:十大新特性速览
前端·javascript·github
雾恋1 小时前
我用 trae 写了一个菜谱小程序(灶搭子)
前端·javascript·uni-app
不死鸟.亚历山大.狼崽子1 小时前
无法将“pnpm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
npm
Bdygsl2 小时前
Node.js(1)—— Node.js介绍与入门
node.js
烛阴2 小时前
TypeScript 中的 `&` 运算符:从入门、踩坑到最佳实践
前端·javascript·typescript
ZhuAiQuan3 小时前
[electron]开发环境驱动识别失败
前端·javascript·electron
nyf_unknown3 小时前
(vue)将dify和ragflow页面嵌入到vue3项目
前端·javascript·vue.js
胡gh3 小时前
数组开会:splice说它要动刀,map说它只想看看。
javascript·后端·面试
胡gh3 小时前
浏览器:我要用缓存!服务器:你缓存过期了!怎么把数据挽留住,这是个问题。
前端·面试·node.js