简介
在本文中,我们将介绍如何使用 Koa.js 搭建一个多人博客。Koa.js 是一个基于 Node.js 的 Web 应用框架,具有轻量、灵活、易扩展等特点,用于快速构建 Web 应用程序,特别是对于 API 应用程序。本文将涉及到 Koa.js 的基本概念和用法、使用 MongoDB 存储数据、使用模板引擎渲染页面和使用第三方模块等。
前置知识
- 了解 JavaScript 和 Node.js
- 了解基本的 HTTP 协议和 Web 开发相关的知识
环境准备
本项目使用以下环境和工具:
- Node.js
- MongoDB
项目初始化
首先,我们需要创建一个空白的文件夹用作项目目录,然后通过以下命令进入该目录:
cd project_folder
接下来,我们使用 npm 初始化该项目:
npm init -y
该命令会创建一个 package.json 文件,其中包含该项目的基本信息和依赖项。
接着,我们需要安装必要的依赖项。在本项目中,我们将使用以下模块:
- koa
- koa-router
- koa-bodyparser
- mongoose
- ejs
- marked
使用以下命令安装这些依赖项:
npm install koa koa-router koa-bodyparser mongoose ejs marked --save
构建基本框架
创建一个 main.js 文件,该文件将作为主要的服务器逻辑。在该文件中,我们需要完成以下操作:
导入必要的模块
const Koa = require('koa') const Router = require('koa-router') const bodyParser = require('koa-bodyparser') const mongoose = require('mongoose') const ejs = require('ejs') const marked = require('marked')
初始化 Koa 和路由
const app = new Koa() const router = new Router()
连接 MongoDB 数据库
mongoose.connect('mongodb://localhost:27017/blog', { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false }).then(() => { console.log('Connected to database') }).catch((err) => { console.log(err) })
创建一个模型来表示文章
const PostSchema = new mongoose.Schema({ title: String, content: String, created: { type: Date, default: Date.now } }) const Post = mongoose.model('Post', PostSchema)
创建一个首页路由
router.get('/', async (ctx) => { const posts = await Post.find().sort('-created') const html = ejs.render(` <% for(let i=0; i<posts.length; i++) { %> <div> <h2><%= posts[i].title %></h2> <p><%= marked(posts[i].content) %></p> </div> <% } %>`, {posts: posts}) ctx.body = html })
创建一个创建文章的路由
router.get('/post/new', async (ctx) => { const html = ejs.render(` <form method="post" action="/post"> <input type="text" name="title" placeholder="Title" required> <textarea name="content" placeholder="Content" required></textarea> <input type="submit" value="Publish"> </form> `, {}) ctx.body = html }) router.post('/post', async (ctx) => { const post = new Post(ctx.request.body) try { await post.save() ctx.redirect('/') } catch (err) { console.log(err) } })
启动服务器
app.use(bodyParser()) app.use(router.routes()) app.use(router.allowedMethods()) app.listen(3000, () => { console.log('Server started') })
现在,运行以下命令启动服务器:
node main.js
在浏览器中输入网址 http://localhost:3000 ,即可访问该博客系统的首页。
高级功能
以上仅为一个最基本的博客系统,它缺乏用户认证、分页、评论等其他功能。这里简单介绍一些高级功能的实现。
用户认证
在实现用户认证前,请确保已经安装了以下依赖:
- passport
- passport-local
- password-hash-and-salt
首先,我们需要定义一个 User 模型来表示用户数据:
const UserSchema = new mongoose.Schema({ username: String, password: String }) UserSchema.plugin(passportLocalMongoose) const User = mongoose.model('User', UserSchema)
然后,我们需要启用 passport:
const passport = require('koa-passport') const LocalStrategy = require('passport-local').Strategy const salt = require('password-hash-and-salt').salt passport.serializeUser((user, done) => { done(null, user.id) }) passport.deserializeUser((id, done) => { User.findById(id, (err, user) => { done(err, user) }) }) passport.use(new LocalStrategy({ usernameField: 'username', passwordField: 'password' }, (username, password, done) => { User.findOne({username: username}, (err, user) => { if (err) { return done(err) } if (!user) { return done(null, false, {message: 'Incorrect username'}) } salt(password).hash(user.password.hash, (err, hash) => { if (err) { return done(err) } if (hash !== user.password.hash) { return done(null, false, {message: 'Incorrect password'}) } return done(null, user) }) }) }))
定义好 User 模型和 passport 后,我们需要在路由中加入认证逻辑:
router.post('/login', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }) ) router.post('/register', async (ctx) => { const user = new User({ username: ctx.request.body.username, password: ctx.request.body.password }) await user.setPassword(ctx.request.body.password) try { await user.save() ctx.redirect('/') } catch (err) { console.log(err) } })
现在,我们可以在登录和注册页面加入表单,然后在需要认证的路由处理函数中加上 passport.authenticate 认证逻辑即可。
分页
在这里,我们将使用 koa-easy-paginate 模块来实现分页功能,它可以方便地将数据库查询结果分页。
首先,我们需要安装 koa-easy-paginate 模块:
npm install koa-easy-paginate --save
我们需要在路由中加入分页逻辑:
router.get('/page/:page', async (ctx) => { const [pageQuery, itemCount] = await ctx.pager.getPageQuery(Post.find().sort('-created')) const posts = await pageQuery.exec() const html = ejs.render(` <% for(let i=0; i<posts.length; i++) { %> <div> <h2><%= posts[i].title %></h2> <p><%= marked(posts[i].content) %></p> </div> <% } %> <div class="pagination"> <% for(let i=1; i<=pages; i++) { %> <% if (i == currentPage) { %> <span><%= i %></span> <% } else { %> <a href="/page/<%= i %>"><%= i %></a> <% } %> <% } %> </div> `, { posts: posts, pages: ctx.pager.totalPages(), currentPage: ctx.pager.currentPage() }) ctx.body = html })
现在,我们可以在首页的底部加入分页控件了。
评论
在这里,我们将使用 mongoose-comment-system 模块来实现评论功能,它可以轻松地将评论功能添加到任何 Mongoose 模型中。
首先,我们需要安装 mongoose-comment-system 模块:
npm install mongoose-comment-system --save
接着,我们需要对 Post 模型进行扩展:
const commentSystem = require('mongoose-comment-system') const PostSchema = new mongoose.Schema({ title: String, content: String, created: { type: Date, default: Date.now } }) PostSchema.plugin(commentSystem) const Post = mongoose.model('Post', PostSchema)
最后,我们需要在路由中加入评论逻辑:
router.post('/post/:id/comments', async (ctx) => { const post = await Post.findById(ctx.params.id) const comment = await post.addComment({ author: ctx.request.body.author, body: ctx.request.body.body }) ctx.redirect(`/post/${ctx.params.id}`) }) router.get('/post/:id', async (ctx) => { const post = await Post.findById(ctx.params.id) const comments = await post.getCommentTree() const html = ejs.render(` <h2>${post.title}</h2> <div>${marked(post.content)}</div> <br> <% for(let i=0; i<comments.length; i++) { %> <div> <p><%= comments[i].author %>:</p> <p><%= marked(comments[i].body) %></p> <a href="#" class="reply">回复</a> <form method="post" action="/post/<%= post.id %>/comments" class="reply-form" hidden> <input type="text" name="author" placeholder="Author" required> <textarea name="body" placeholder="Comment" required></textarea> <input type="submit" value="Reply"> </form> <hr> </div> <% } %> <form method="post" action="/post/<%= post.id %>/comments"> <input type="text" name="author" placeholder="Author" required> <textarea name="body" placeholder="Comment" required></textarea> <input type="submit" value="Comment"> </form> `, { post: post, comments: comments }) ctx.body = html })
现在,我们可以在文章页面下方加入评论区了。
总结
在本文中,我们使用 Koa.js 搭建了一个多人博客系统,并实现了用户认证、分页和评论等功能。通过对 Koa.js 的学习和实践,我们可以对 Node.js Web 开发有更深入的理解,同时掌握了实际开发中的一些技巧和方法。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65912dceeb4cecbf2d6674cb