Gitee project address

Basic use of KOA

The directory structure

The use of koa

Creating an App

  1. Create an app.js file and import the required third-party plug-ins.
var Koa = require('koa');
var views = require('koa-views');
var bodyParser = require('koa-bodyparser');
const serve = require('koa-static');
const render  = require('koa-art-template');
const path = require('path');
var {router} = require('./router');
Copy the code
  1. Create the app and listen on the port
var app = new Koa()
app.listen(3001)
Copy the code

Use the routing

  1. Configure routes. Configure routes in router.js
var Router = require('koa-router')

var router = new Router()

// Configure the route
router.get('/'.async (ctx) => {
    // Return data equivalent to the original res.writehead () res.end()
    ctx.body = 'home'
})
// Configure dynamic routing
router.get('/newsdetail/:id'.async (ctx) => {
    console.log(ctx.params);
})
Copy the code
  1. Start routing in app.js
// router.allowedMethods() is called after all the routing middleware, at which point the response header is set according to ctx.status
app
    .use(router.routes())
    .use(router.allowedMethods())
Copy the code

Gets the GET request parameters

GET: There are two receiving modes: Query and queryString

  • Query: Returns a formatted argument object
  • Querystring: Returns a request string
router.get('/newsContent'.async (ctx) => {
    // CTX gets the get pass value
    console.log(ctx.query);
    console.log(ctx.querystring);
    // request in CTX
    console.log(ctx.request);
    console.log(ctx.params);
})
Copy the code

Receive POST request parameters

  1. Introducing middleware
/ /! Post parameter parsing middleware
app.use(bodyParser());
Copy the code
  1. To obtain parameters
router.post('/doAdd'.async(ctx) => {
    // Get the data submitted by the form
    console.log(ctx.request.body);
})
Copy the code

Use of middleware

  1. Application-level middleware

Middleware defined in app.js, executed before the route is matched.

app.use(async(ctx, next) => {
	// Configure ctx.state.userInfo in middleware to use userInfo in any page
    ctx.state.userInfo = 'name'
    console.log('First middleware before Next');
    // Continue matching down
    await next()
    console.log('First middleware after Next');
})
Copy the code
  1. Error middleware

When an error occurs, return to the corresponding page.

app.use(async(ctx, next) => {
   console.log('Second middleware before Next');
    await next()
    console.log('Second middleware after Next');
    // When all routes match, a 404 page is returned
    if (ctx.status == 404) {
        ctx.status = 404
        ctx.body = 'This is a 404 page'}})Copy the code
  1. Routing level middleware
router.get('/news'.async(ctx, next) => {
    console.log('This is a news page'); 
    await next()
})
router.get('/news'.async(ctx) => {
    ctx.body = 'This is a news page'
})
Copy the code

Middleware execution flow

  • Execute the middleware from the top down
  • Next is encountered to execute the next middleware
  • After the middleware completes execution, the route is matched
  • After the route matching is complete, the code after next of the middleware is executed from the bottom up

The output

  1. Enter ‘/news’ route. The route is successfully matched

Output:

  • First middleware before Next
  • Second middleware before next
  • This is a news page
  • Second middleware after next
  • After the first middleware, Next
  1. Failed to match route by entering ‘/news1’ route

Output:

  • First middleware before Next
  • Second middleware before next
  • Second middleware after next
  • After the first middleware, Next

Open static Resources

Configure the static resource middleware and open the files in the static folder.

app.use(serve('static'))
Copy the code

A template engine

Ejs template engine

  1. Use the EJS template engine
// The template is an EJS file
// app.use(views('views', { extension: 'ejs' }))
// The template is an HTML file
app.use(views('views', { map: { html: 'ejs' }}))
Copy the code

2 templates

<! -- header.html -->
<h1>This is a header module</h1>
<! -- index.html -->
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <link rel="stylesheet" href="/css/base.css">
</head>
<body>
    <p>Include () imports the HTML file, '-' and parses it</p>
    <%- include('public/header.html') %>
    <h1>Template engine - HTML</h1>
    <h2><%=title%></h2>
    <ul>
        <%for(var i = 0; i < list.length; i++) {%>
            <li><%=list[i]%></li>The < %} % ></ul>
    <p>Public data configure ctx.state.userInfo in middleware -- <%= userInfo %></p>
    <img src="/images/timg.jpg" alt="">
</body>
</html>
Copy the code
  1. Using a template engine
router.get('/'.async (ctx) => {
    let title = 'Hello, EJs'
    let arr = [111.222.333]
    await ctx.render('index', {
        title: title,
        list: arr
    })
})
Copy the code

Art-template template engine

  1. Introducing a template engine
render(app, {
    root: path.join(__dirname, 'views'),  // View position
    extname: '.html'./ / suffix
    debug: process.env.NODE_ENV ! = ='production'   // Enable debugging mode
});
Copy the code
  1. The template
<! -- header.html -->
<h1>This is a header module</h1>
<! -- index.html -->
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
    <link rel="stylesheet" href="/css/base.css">
</head>
<body>
    <h1>Template engine - Koa-art-template</h1>
    <hr>
    <h3>The child templates</h3>
    {{include './public/header.html'}}
    <h2>{{title}}</h2>
    <hr>
    <h3>cycle</h3>
    <ul>
        {{each arr}}
        <li>{{$value}}</li>
        {{/each}}
    </ul>
    <hr>
    <h3>conditions</h3>
    {{if num > 20}}
    <strong>More than 20</strong>
    {{else}}
    <strong>Less than 20</strong>
    {{/if}}
    <hr>
    <img src="/images/timg.jpg" alt="">
</body>
</html>
Copy the code
  1. Using a template engine
router.get('/'.async (ctx) => {
    let title = 'Hello, art-template'
    let arr = [111.222.333]
    let num = 10
    await ctx.render('index', { title, arr, num })
})
Copy the code

Use of cookies and sessions

The use of cookies

  1. Server setting cookie

router.get('/'.async (ctx) => {
    // KoA does not support setting Chinese cookies directly
    var userInfo = new Buffer('Joe').toString('base64')
    ctx.cookies.set('userInfo', userInfo, {
        maxAge: 1000 * 60 * 60.httpOnly: true.// True indicates that only the server can access the cookie. False indicates that both the client and server can access the cookie
    })
    await ctx.render('artIndex')})Copy the code
  1. Use cookies on the server
router.get('/news'.async (ctx) => {
    var cookieData = ctx.cookies.get('userInfo')
    var transformCookie = new Buffer(cookieData, 'base64').toString()
    console.log('Get cookie information', transformCookie);
    await ctx.render('news')})Copy the code
  1. The client obtains cookies
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <h2>News page</h2>
    <script>
        console.log(document.cookie)
    </script>
</body>
</html>
Copy the code

HttpOnly: true: Cookies cannot be obtained via document.cookie on news. HTML pages. When httpOnly: false, a cookie can be obtained via document.cookie on the news. HTML page.

The use of the session

  1. The import file
const session = require('koa-session')
Copy the code
  1. Configuring session Middleware
app.keys = ['some secret hurr']; // Cookie signature
const CONFIG = {
    key: 'koa.sess'./ * * * / by default
    maxAge: 86400000.// Expiration time of cookie
    autoCommit: true./ * * * /
    overwrite: true./ * * * /
    httpOnly: true./** true Only the server side can get cookies */
    signed: true./** Default signature */
    rolling: false./** Forcibly set the cookie on each request, which resets the cookie expiration time */
    renew: true./** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/
    secure: false./** (boolean) secure cookie*/
    sameSite: null./** (string) session cookie sameSite options (default null, don't set it) */
};
   
  app.use(session(CONFIG, app));
Copy the code
  1. Set up the session
router.get('/login'.async (ctx) => {
    / / set the session
    ctx.session.userInfo = 'the session information'
    ctx.body = 'Login page'
})
Copy the code
  1. Access to the session
router.get('/'.async (ctx) => {
    / / get the session
    console.log('Get Session info', ctx.session.userInfo);
    await ctx.render('artIndex')})Copy the code

Using the mongodb database

The directory structure

Connect to mongodb database, complete add, delete, change and check function, use third-party plug-in “mongodb”: “^3.6.3”

  1. Views page file
  • Home page index. HTML
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <h1>Template engine - Koa-art-template</h1>
    <hr>
    <a href="/user/add">increase</a>
    <table>
        <tr>
            <th>The name</th>
            <th>age</th>
            <th>gender</th>
            <th>state</th>
            <th>operation</th>
        </tr>
        {{each list}}
            <tr>
                <td>{{$value.username}}</td>
                <td>{{$value.age}}</td>
                <td>{{$value.sex}}</td>
                <td>{{$value.status}}</td>
                <td><a href="/user/edit? id={{@$value._id}}">Modify the</a><a href="/user/delete? id={{@$value._id}}">delete</a></td>
            </tr>
        {{/each}}
    </table>
</body>
</html>
Copy the code
  • Add page add.html
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <h2>New Data Page</h2>
    <form action="/user/doAdd" method="POST">User name:<input type="text" name="username">Age:<input type="text" name="age">Gender:<input type="text" name="sex">Status:<input type="text" name="status">
    <input type="submit" value="Submit">
    </form>
</body>
</html>
Copy the code
  • Modify the page edit.html
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <h2>Edit data page</h2>
    <form action="/user/doEdit" method="POST">
    <input type="hidden" name="id" value="{{@list._id}}">User name:<input type="text" name="username" value="{{list.username}}">Age:<input type="text" name="age" value="{{list.age}}">Gender:<input type="text" name="sex" value="{{list.sex}}">Status:<input type="text" name="status" value="{{list.status}}">
    <input type="submit" value="Submit">
    </form>
</body>
</html>
Copy the code
  1. The module folder

It is used to connect to the database, encapsulate and export the method of adding, deleting, changing and checking

  • Example Export the database configuration information – config.js
var app = {
   dbUrl: 'mongodb://localhost:27017'.dbName: 'koa'
}
module.exports = app
Copy the code
  • Encapsulate operation database method – db.js

const MongoClient = require('mongodb').MongoClient;
const  ObjectID = require('mongodb').ObjectID
const Config = require('./config')
class Db {
    // Use singleton multiple instances are not shared
    static getInstance() {
        if(! Db.instance) { Db.instance =new Db()
        }
        return Db.instance
    }
    constructor() {
        this.dbClient = null
    }
    connect() {
        return new Promise((resolve, reject) = > {
            if (!this.dbClient) {
                MongoClient.connect(Config.dbUrl, (err, client) = > {
                    if(err) {
                        reject(err)
                    }else {
                        var db = client.db(Config.dbName)
                        this.dbClient = db
                        resolve(this.dbClient)
                    }
                })
            }
            else resolve(this.dbClient)
        })
    }
    // find method find collection name find rule
    find(collectionName, json) {
        return new Promise((resolve, reject) = > {
            this.connect().then((db) = > {
                var result = db.collection(collectionName).find(json)
                result.toArray((err, docs) = > {
                    if (err) reject(err)
                    resolve(docs)
                })
            })
        })
    }
    // Update method Updates the updated data of the set name to be updated
    update(collectionName, json1, json2) {
        return new Promise((resolve, reject) = > {
            this.connect().then(db= > {
                db.collection(collectionName).updateOne(json1, {
                    $set: json2
                }, (err, result) = > {
                    if(err) reject(err)
                    resolve(result)
                })
            })
        })
    }
    // The insert method inserts the data that the collection name inserts
    insert(collectionName, json) {
        return new Promise((resolve, reject) = > {
            this.connect().then((db) = > {
                db.collection(collectionName).insertOne(json, (err, result) = > {
                    if(err) reject(err)
                    resolve(result)
                })
            })
        })
    }
    // Delete method Delete collection name delete field
    remove(collectionName, json) {
        return new Promise((resolve, reject) = > {
            this.connect().then((db) = > {
                db.collection(collectionName).removeOne(json, (err, result) = > {
                    if(err) reject(err)
                    resolve(result)
                })
            })
        })
    }
    // Based on the returned ID, generate the style ID required by mongodb
    getObjectId(id) {
        return new ObjectID(id)
    }
}

module.exports = Db.getInstance()

Copy the code
  1. The router file
  • User Route configuration user.js
var Router = require('koa-router')
var DB = require('.. /module/db')

var userRouter = new Router()

// Configure the route
userRouter.get('/'.async (ctx) => {
    var result = await DB.find('user', {})
    await ctx.render('artIndex', {list: result})
})

userRouter.get('/add'.async (ctx) => {
    await ctx.render('add')
})

userRouter.post('/doAdd'.async (ctx) => {
    let addData = ctx.request.body
    const result = await DB.insert('user', addData)
    try {
        if (result.result.ok) {
            ctx.redirect('/user')}}catch (error) {
        ctx.redirect('/user/add')
    }
})

userRouter.get('/edit'.async (ctx) => {
    // Get user information based on id
    let userId = ctx.query.id
    const result = await DB.find('user', { "_id": DB.getObjectId(userId) })
    await ctx.render('edit', {list: result[0]})
})

userRouter.post('/doEdit'.async (ctx) => {
    let userData = ctx.request.body
    var  id = userData.id
    var username = userData.username
    var age = userData.age
    var sex = userData.sex
    var status = userData.status
    const result = await DB.update('user', {"_id": DB.getObjectId(id)}, { username, age, sex, status })
    try {
        if (result.result.ok) {
            ctx.redirect('/user')}}catch (error) {
        ctx.redirect('/user/add')
    }
})
userRouter.get('/delete'.async (ctx) => {
    let id = ctx.query.id
    const result = await DB.remove('user', { "_id": DB.getObjectId(id) })
    try {
        if (result.result.ok) {
            ctx.redirect('/user')}}catch (error) {
    }
})

module.exports = userRouter
Copy the code
  • Router.js is configured under the primary route
var Router = require('koa-router')
var router = new Router()

var userRouter = require('./user')

// Configure child routes and start routes
router.use('/user', userRouter.routes())

module.exports = router
Copy the code
  1. Entry file app.js
var Koa = require('koa');
var bodyParser = require('koa-bodyparser');
const render  = require('koa-art-template');
const path = require('path');
var router = require('./router/router');

var app = new Koa()

// Parse post request data
app.use(bodyParser())

// ! art-template 
render(app, {
    root: path.join(__dirname, 'views'),  // View position
    extname: '.html'./ / suffix
    debug: process.env.NODE_ENV ! = ='production'   // Enable debugging mode
});

// todo starts the route
app
    .use(router.routes())
    .use(router.allowedMethods())

app.listen(3001)
Copy the code