Construction of koa2 view layer for Js full stack development

Keywords: npm JSON Database Programming

koa2 view layer construction

Next to the previous one koa2 routing and mvc building in Js full stack development Let's continue to learn about koa2. In the previous article, we split the project into route, controller and service layers according to the mvc architecture, but the view layer and controller layer are mixed together, and there is no split. In this article, we will use templates and static plug-ins to split the view layer, and make a simple summary of the use of Nunjucks template package.

Article catalog

1. Template and static middleware installation

Or npm for installation

npm install koa-nunjucks-2 -save
npm install koa-static -save

2. project structure

├── controller/
│ ├── home.js
├── service/
│ ├── home.js
├── views/
│ ├── common/
│ ├── header.html
│ ├── footer.html
│ ├── layout.html
│ ├── layout-home.html
│ ├── home/
│ ├── index.html
│ ├── login.html
│ ├── success.html
├── public/
│ ├── home/
│ ├── main.css
├── app.js
├── router.js
├── package.json

Three app.js Entrance method

app.js In the entry method, the npm packages of koa-nunjucks-2 and koa static are introduced first, and then their storage paths and relevant parameters are specified respectively.

const Koa = require('koa')
const path = require('path')
const bodyParser = require('koa-bodyparser')
const nunjucks = require('koa-nunjucks-2')
const staticFiles = require('koa-static')

const app = new Koa()
const router = require('./router')

// Specify the public directory as the static resource directory to store js css images, etc
app.use(staticFiles(path.resolve(__dirname, "./public"),{
  maxage: 30*24*60*60*1000
}))

app.use(nunjucks({
  ext: 'html',
  path: path.join(__dirname, 'views'), // Specify view directory
  nunjucksConfig:{
    trimBlocks: true // Turn on escape prevention Xss
  }
}))

app.use(bodyParser())
router(app)
app.listen(3000, () => {
  console.log('server is running at http://localhost:3000')
})

4. Use of views layer

First, the public parent class layout template is introduced, and then other public templates inherit the parent class public template. Then the detailed view pages inherit the corresponding public template.

  • layout.html Layout template
<!DOCTYPE html>
<html>
<head>
    <title>{{title}}</title> 
    <meta name="viewport" content="width=device-width, initial-scale=1">
    {% block head %} {% endblock %}
</head>
<body>
    {% include "./header.html" %}
    {% block body %}
    {% endblock %}
    
    {% include "./footer.html" %}
    {% block content %}
    {% endblock %}
</body>

</html>
  • layout-home.html
{% extends "./layout.html" %} 

{% block head %}
<link rel="stylesheet" href="/home/main.css">
{% endblock %}

{% block body %}
  {% block homeBanner %}
  {% endblock %}

<div class="show_time">
    <div class="feature-con">
        <ul class="feature fn-clear">
            <li class="feature-item"><i class="ico"></i>
                <h4 class="tit">Free resources</h4>
            </li>
            <li class="feature-item"><i class="ico"></i>
                <h4 class="tit">about</h4>
            </li>
        </ul>
    </div>
</div>
{% endblock %}
  • index.html
{% extends "common/layout-home.html" %} 
{% block homeBanner %}
<div class="banner_box">
    <div class="banner_inner">
        <h2 class="slogan">Gathering talents in the world</h2>
        <a href="/login" title="gogogo" class="btn" id="gogogo">Sign in</a>
    </div>
</div>
{% endblock %}
{% block content %}
<div class="hp-dialog">
  <div class="hp-box">
    <form action="/user/register" method="post">
      <h1>Login page</h1>
      <p class="error">{{content}}</p>
      <input type="text" name="name" placeholder="Please enter the user name: dahlin">
      <input type="password" name="password" placeholder="Please enter the password: 123456">
      <button>{{btnName}}</button>
    </form>
  </div>
</div>
,,
{% endblock %}

The basic order is index.html Inherit from layout-home.html ,layout-home.html Inherited from layout.html .

5. Use of controller layer

Call the corresponding views layer template in the controller

const HomeService = require('../service/home')
module.exports = {
  index: async(ctx, next) => {
    await ctx.render("home/index", {title: "xxxx Welcome"})
  },
  login: async(ctx, next) => {
    await ctx.render('home/login',{
      btnName: 'Submit'
    })
  },
  register: async(ctx, next) => {
    let params = ctx.request.body
    let name = params.name
    let password = params.password
    let res = await HomeService.register(name,password)
    if(res.status == "-1"){
      await ctx.render("home/login", res.data)
    }else{
      ctx.state.title = "Personal Center"
      await ctx.render("home/success", res.data)
    }
  }
}

6. Routing router.js

All URLs are initiated from the route. The specific route matches the corresponding url. The url calls the corresponding method in the controller.

const router = require('koa-router')()
const HomeController = require('./controller/home')
module.exports = (app) => {
  router.get( '/', HomeController.index )
  router.get('/user', HomeController.login)
  router.post('/user/register', HomeController.register)
  app.use(router.routes())
    .use(router.allowedMethods())
}

The model data model layer is not involved in this chapter, which will be summarized together with the database part in the next chapter.

7. Nunjucks grammar basis

7.1 basic grammar

First, we need to understand several features of nunjuks

variable

  {{ username }}

  {{ foo.bar }}
  {{ foo["bar"] }}

If the value of the variable is undefined or null, it will not be displayed.
filter

  {{ foo | title }}
  {{ foo | join(",") }}
  {{ foo | replace("foo", "bar") | capitalize }}

if judgment

  {% if variable %}
    It is true
  {% endif %}

  {% if hungry %}
    I am hungry
  {% elif tired %}
    I am tired
  {% else %}
    I am good!
  {% endif %}

for loop

  var items = [{ title: "foo", id: 1 }, { title: "bar", id: 2}]
  <h1>Posts</h1>
  <ul>
  {% for item in items %}
    <li>{{ item.title }}</li>
  {% else %}
    <li>This would display if the 'item' collection were empty</li>
  {% endfor %}
  </ul>

Macro macro

Macros: define reusable content, similar to functions in programming languages

  {% macro field(name, value='', type='text') %}
  <div class="field">
    <input type="{{ type }}" name="{{ name }}"
          value="{{ value | escape }}" />
  </div>
  {% endmacro %}

Next, you can use field as a function:

  {{ field('user') }}
  {{ field('pass', type='password') }}

For more grammar information, please refer to Official documents

7.1 inherited functions

The common structure of web pages is mostly the head, intermediate and tail. For multiple pages under the same website, the content of the head and tail are basically the same. So we can use inheritance function to write.

Define one first layout.html

  <html>
    <head>
      {% block head %}
      <link rel="stylesheet">
      {% endblock %}
    </head>  
    <body>
      {% block header %}
      <h1>this is header</h1>
      {% endblock %}

      {% block body %}
      <h1>this is body</h1>
      {% endblock %}

      {% block footer %}
      <h1>this is footer</h1>  
      {% endblock %}

      {% block content %}
      <script>
        //this is place for javascript
      </script>
      {% endblock %}
    </body>
  </html>

layout defines five modules, named head, header, body, footer and content. Header and footer are common, so they are basically static. The modification of business code only needs to be done in the body content body, and the business stylesheet and business script need to be introduced in the head and bottom content respectively.

Next, we define a business level view page: home.html

  {% extends 'layout.html' %}

  {% block head %}
  <link href="home.css">
  {% endblock %}

  {% block body %}
  <h1>home Page content</h1>
  {% endblock %}

  {% block content %}
  <script src="home.js"></script>
  {% endblock%}

Final home.html The output is as follows:

  <html>
    <head>
      <link href="home.css">
    </head>  
    <body>
      <h1>this is header</h1>
      <h1>home Page content</h1>
      <h1>this is footer</h1>  
      <script src="home.js"></script>
    </body>
  </html>

Posted by ShugNorris on Sun, 28 Jun 2020 19:06:29 -0700