Js全栈开发之koa2视图层搭建

koa2视图层搭建

接着上一篇《Js全栈开发之koa2路由与mvc搭建初步》来继续学习koa2,上一篇将koa2项目按mvc架构拆分了一下,只拆分出了路由,控制器和服务层,而视图层和控制器层混在了一起,没有进行拆分,本篇将使用模板和静态插件对视图层进行拆分,并对Nunjucks模板包的使用做简单的汇总。

1. 模板与静态中间件安装

还是使用npm进行安装

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

2. 项目结构

├── 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

3. app.js 入口方法

app.js 入口方法方法中先引入koa-nunjucks-2和koa-static两个中间件的npm包,之后分别指定它们的存放路径及相关参数。

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')

// 指定 public目录为静态资源目录,用来存放 js css images 等
app.use(staticFiles(path.resolve(__dirname, "./public"),{
  maxage: 30*24*60*60*1000
}))

app.use(nunjucks({
  ext: 'html',
  path: path.join(__dirname, 'views'), // 指定视图目录
  nunjucksConfig:{
    trimBlocks: true // 开启转义 防Xss
  }
}))

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

4. views层使用

先引入公共的父类布局模板,其他的公共模板再继承父类的公共模板。之后详细的各类视图页面再继承对应的公共模板。

  • layout.html 布局模板
<!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">免费资源</h4>
            </li>
            <li class="feature-item"><i class="ico"></i>
                <h4 class="tit">关于</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">汇聚天下英才</h2>
        <a href="/login" title="gogogo" class="btn" id="gogogo">登录</a>
    </div>
</div>
{% endblock %}
{% block content %}
<div class="hp-dialog">
  <div class="hp-box">
    <form action="/user/register" method="post">
      <h1>登录页面</h1>
      <p class="error">{{content}}</p>
      <input type="text" name="name" placeholder="请输入用户名:dahlin">
      <input type="password" name="password" placeholder="请输入密码:123456">
      <button>{{btnName}}</button>
    </form>
  </div>
</div>
、、
{% endblock %}

基本顺序就是 index.html继承自layout-home.html,layout-home.html继承自layout.html。

5. controller层使用

在controller里面调用对应的views层模板


const HomeService = require('../service/home')
module.exports = {
  index: async(ctx, next) => {
    await ctx.render("home/index", {title: "xxxx欢迎您"})
  },
  login: async(ctx, next) => {
    await ctx.render('home/login',{
      btnName: '提交'
    })
  },
  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 = "个人中心"
      await ctx.render("home/success", res.data)
    }
  }
}

6. 路由router.js

所有的url都是从路由中发起的,特定的路由匹配与之对应的url,url调用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())
}

本章没有涉及到model数据模型层,将在下一章和数据库部分一同总结汇总。

7. Nunjucks语法 基础

7.1 基础语法

首先我们需要了解 Nunjucks 的几个特性

变量

  {{ username }}

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

如果变量的值为 undefinednull ,将不予显示。
过滤器

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

if 判断

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

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

for 循环

  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 field(name, value='', type='text') %}
  <div class="field">
    <input type="{{ type }}" name="{{ name }}"
          value="{{ value | escape }}" />
  </div>
  {% endmacro %}

接下来就可以把 field 当作函数一样使用:

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

更多语法内容请查阅官方文档

7.1 继承功能

网页常见的结构大多是头部、中间体加尾部,同一个网站下的多个网页,头部和尾部内容通常来说基本一致。于是我们可以采用继承功能来进行编写。

先定义一个 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 定义了五个模块,分别命名为:headheaderbodyfootercontentheaderfooter 是公用的,因此基本不动。业务代码的修改只需要在 body 内容体中进行、业务样式表和业务脚本分别在头部 head 和底部 content 中引入。

接下来我们再定义一个业务级别的视图页面:home.html

  {% extends 'layout.html' %}

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

  {% block body %}
  <h1>home 页面内容</h1>
  {% endblock %}

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

最终的 home.html 输出后如下所示:

  <html>
    <head>
      <link href="home.css">
    </head>  
    <body>
      <h1>this is header</h1>
      <h1>home 页面内容</h1>
      <h1>this is footer</h1>  
      <script src="home.js"></script>
    </body>
  </html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值