iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

iKcamp發表於2018-01-12

視訊地址:www.cctalk.com/v/151149238…

iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

處理靜態資源

無非花開花落,靜靜。

指定靜態資源目錄

這裡我們使用第三方中介軟體: koa-static

安裝並使用

安裝 koa-static

npm i koa-static -S
複製程式碼

修改 app.js,增加並指定 /public 目錄為靜態資源目錄。

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

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

  // 指定 public目錄為靜態資源目錄,用來存放 js css images 等
  app.use(staticFiles(path.resolve(__dirname, "./public")))

  app.use(nunjucks({
    ext: 'html',
    path: path.join(__dirname, 'views'),
    nunjucksConfig: {
      trimBlocks: true
    }
  }));

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

之後我們對專案的檢視進行美化,使之更為賞心悅目。

增加樣式檔案

/public/home/ 目錄下新增樣式檔案 main.css,內容如下:

  *{
    padding: 0;
    margin: 0;
  }

  body,html{
    font-size: 14px;
    color: #000;
    background: #fff;
    font-family: Helvetica Neue,Helvetica,Segoe UI,Arial,Hiragino Sans GB,Microsoft YaHei;
    -webkit-font-smoothing: antialiased;
    position: relative;
  }
  .fn-clear:after {
    visibility: hidden;
    display: block;
    font-size: 0;
    content: " ";
    clear: both;
    height: 0
  }

  .fn-clear {
    zoom:1}
  a {
    color: #0366d6;
    text-decoration: none; 
  }

  a:hover {
    text-decoration: none; 
  }

  .header{
    width: 100%;
    background-color: #474747;
  }

  .header-box{
    height: 30px;
    line-height: 30px;
    font-size: 12px;
    letter-spacing: 2px;
    color: #d5d5d5;
    transition: color .3s;
  }

  .header-box>.logo{
    letter-spacing: 0;
    font-size: 12px;
  }

  .wraper{
    width: 1200px;
    margin: 0 auto;
  }

  .container{
    min-height: 500px;
    padding: 80px 0;
  }

  .footer{
    background: #262a30;
    padding: 50px 0;
    border-top: 1px solid #ddd;
    color: #999;
    font-size: 16px;
  }
  .footer-box{
    width: 800px;
    margin: 0 auto;
    text-align: center;
  }
  .banner_box{
    width: 100%;
    min-width: 1200px;
    height: 438px;
    background: url(https://res.hjfile.cn/cc/cctalk.hujiang.com/home/images/banner-2QEtv.jpg?2QEtv) 50% no-repeat;
    background-size: cover;
  }
  .banner_box>.banner_inner{
    width: 1200px;
    margin: 0 auto;
    padding-top: 112px;
  }
  .banner_inner>.slogan{
    width: 427px;
    height: 54px;
    background: url(https://res.hjfile.cn/cc/cctalk.hujiang.com/home/images/slogan@2x-3x9xM.png?3x9xM);
    background-size: 100% auto;
    margin: 0 auto 25px;
    text-indent: -99999rem;
  }
  .banner_inner>.des{
    margin-bottom: 24px;
    font-size: 16px;
    line-height: 1.9;
    color: #fff;
    text-align: center;
  }
  .banner_inner>.btn{
    display: block;
    margin: 0 auto;
    width: 220px;
    height: 48px;
    font-size: 20px;
    line-height: 48px;
    border-radius: 4px;
    background-color: #15a9ff;
    color: #fff;
    text-align: center;
    text-decoration: none;
    box-shadow: 0 2px 6px rgba(0,0,0,.3);
  }

  .show_time>.feature-con{
    background: #fff;
    border-bottom: 2px solid #f8f8f8;
    min-width: 1200px;
  }
  .feature-con>.feature{
    list-style: none;
    margin: 0 auto;
    padding: 40px 0 60px;
    width: 1200px;
  }
  .feature>.feature-item{
    float: left;
    width: 160px;
    margin: 0;
    padding: 0;
    margin-right: 132px;
  }
  .feature>.feature-item:first-child{
    margin-left: 88px;
  }
  .feature>.feature-item:last-child{
    margin-right: 0;
  }
  .feature .ico{
    display: inline-block;
    width: 160px;
    height: 130px;
    background: url(https://res.hjfile.cn/cc/cctalk.hujiang.com/home/images/feature-icon1@2x-BvNad.png?BvNad);
    background-size: 100% auto;
  }
  .feature>.feature-item:nth-child(2) .ico{
    background-image: url(https://res.hjfile.cn/cc/cctalk.hujiang.com/home/images/feature-icon2@2x-1raFv.png);
  }
  .feature>.feature-item:nth-child(3) .ico{
    background-image: url(https://res.hjfile.cn/cc/cctalk.hujiang.com/home/images/feature-icon3@2x-2y1F0.png);
  }
  .feature>.feature-item:nth-child(4) .ico{
    background-image: url(https://res.hjfile.cn/cc/cctalk.hujiang.com/home/images/feature-icon4@2x-27VL5.png);
  }
  .feature-item>.tit{
    padding: 0;
    margin: 0;
    font-size: 16px;
    line-height: 26px;
    color: #333;
    text-align: center;
    font-weight: 400;
  }
  .feature-item>.des{
    padding: 0;
    margin: 0;
    font-size: 16px;
    line-height: 26px;
    color: #333;
    text-align: center;
    opacity: .5;
  }

  .hp-overlay{
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 99999;
    opacity: .5;
    filter: Alpha(opacity=50);
    background-color: #000;
  }

  .hp-dialog{
    width: 370px;
    border-radius: 5px;
    background-color: #fff;
    outline: 0;
    box-shadow: 0 5px 30px rgba(0,0,0,.2);
    z-index: 1000000;
    position: fixed;
    left: 50%;
    top: 50%;
    -webkit-transform: translate(-50%,-50%);  
    -ms-transform: translate(-50%,-50%);  
    transform: translate(-50%,-50%); 
  }

  .hp-box{
    padding: 12px 30px 30px;
    color: #333;
  }
  .hp-box h1{
    line-height: 48px;
    text-align: center;
    font-size: 20px;
    font-weight: 400;
    margin-bottom: 12px;
  }
  .hp-box .error{
    color: red;
    line-height: 30px;
  }
  .hp-box input{
    display: block;
    width: 100%;
    height: 42px;
    padding: 10px 10px 10px 10px;
    border-radius: 3px;
    border: 1px solid #e5e5e5;
    font-size: 14px;
    line-height: 20px;
    outline: 0;
    -webkit-appearance: none;
    appearance: none;
    -webkit-transition: border .2s ease;
    transition: border .2s ease;
    margin-bottom: 30px;
    box-sizing: border-box;
  }
  .hp-box button{
    display: block;
    width: 100%;
    height: 42px;
    background-color:#44b336;
    border: 0;
    border-radius: 3px;
    color: #fff;
    font-size: 18px;
    line-height: 42px;
    text-align: center;
    outline: 0;
    cursor: pointer;
  }
  .hp-box input:focus,.hp-box input:focus:hover {
    border: 1px solid #44b336
  }

  .hp-box input:hover {
    border: 1px solid #ddd
  }

  .hp-box input::-webkit-input-placeholder {
    color: #ddd
  }

  .hp-box input::-ms-input-placeholder {
    color: #ddd
  }

  .hp-box input::-ms-reveal {
    display: none
  }

  .hp-box input::-ms-clear {
    display: none
  }
  .footer .title{
    font-size: 24px;
  }
  .footer .info{
    letter-spacing: 2px;
  }
複製程式碼

然後修改 views 檢視檔案,按照繼承的方式提取出公用部分。

增加公用檢視

新建 /views/common/header.html

  <header class="header">
      <div class="header-box wraper">Node實戰教程 | <span class="logo">© iKcamp</span></div>
  </header>
複製程式碼

新建 /views/common/footer.html

  <footer class="footer">
      <div class="footer-box wraper">
          <p class="title">滬江Web前端團隊傾情奉獻</p>
          <p><a href="https://github.com/ikcamp">https://github.com/ikcamp</a></p>
          <br>
          <p class="info">iKcamp由滬江Web前端團隊中熱愛原創和翻譯的小夥伴發起,成立於2016年7月,"iK"代表布蘭登·艾克(JavaScript之父)。 追隨JavaScript這門語言所秉持的精神,崇尚開放和自由的我們一同工作、分享、創作,等候更多有趣跳動的靈魂。</p>
          <p class="police">滬ICP備17041059號 ©2017-2018 </p>
      </div>
  </footer>
複製程式碼

新建 /views/common/layout.html。注意,此處有模板變數 title

  <!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.html 就是我們的基礎頁面。現在我們再為 home 建立專用的 layout-home.html,並在裡面引用之前建立的樣式表:

新建 /views/common/layout-home.html。注意,我們在 body 模組裡又增加了一個 homeBanner 模組:

{% 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>
                <p class="des">為天地立心</p>
            </li>
            <li class="feature-item"><i class="ico"></i>
                <h4 class="tit">體系知識</h4>
                <p class="des">為科技立命</p>
            </li>
            <li class="feature-item"><i class="ico"></i>
                <h4 class="tit">實戰專案</h4>
                <p class="des">為大牛繼絕學</p>
            </li>
            <li class="feature-item"><i class="ico"></i>
                <h4 class="tit">線下交流</h4>
                <p class="des">為教育開太平</p>
            </li>
        </ul>
    </div>
</div>
{% endblock %}
複製程式碼

公用部分提取完成之後,重寫 home 互動頁面。此時我們對登入功能的檢視進行美化,有主頁,登入,以及登入後的響應頁面。

重寫 home 業務的檢視

新增 /views/home/index.html 首頁

{% extends "common/layout-home.html" %} 
{% block homeBanner %}
<div class="banner_box">
    <div class="banner_inner">
        <h2 class="slogan">匯聚天下英才</h2>
        <p class="des">iKcamp是由滬江Web前端團隊發起的自由組織<br>我們追隨JavaScript這門語言所秉持的精神,為ITer提供完善的線上學習平臺和知識體系</p>
        <a href="/user" title="gogogo" class="btn" id="gogogo">進入戰場</a>
    </div>
</div>
{% endblock %}
複製程式碼

修改 /views/home/login.html 登入頁面

  {% extends "common/layout-home.html" %} 
  {% block homeBanner %}
  <div class="banner_box">
      <div class="banner_inner">
          <h2 class="slogan">匯聚天下英才</h2>
          <p class="des">iKcamp是由滬江Web前端團隊發起的自由組織<br>我們追隨JavaScript這門語言所秉持的精神,為ITer提供完善的線上學習平臺和知識體系</p>
          <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="請輸入使用者名稱:ikcamp">
        <input type="password" name="password" placeholder="請輸入密碼:123456">
        <button>GoGoGo</button>
      </form>
    </div>
  </div>
  <div class="hp-overlay"></div>
  {% endblock %}
複製程式碼

新增 /views/home/success.html 成功頁面

{% extends "common/layout-home.html" %} 
{% block homeBanner %}
<div class="banner_box">
    <div class="banner_inner">
        <h2 class="slogan">匯聚天下英才</h2>
        <p class="des">iKcamp是由滬江Web前端團隊發起的自由組織<br>我們追隨JavaScript這門語言所秉持的精神,為ITer提供完善的線上學習平臺和知識體系</p>
        <a href="javascript:;" title="gogogo" class="btn" id="gogogo">成功進入戰場</a>        
    </div>
</div>
{% endblock %}
複製程式碼

增加完成後,需要對 home 的處理邏輯進行修改

重寫 home 處理邏輯

修改 /service/home.js

  module.exports = {
    register: async function(name, pwd) {
      let data 
      if(name == 'ikcamp' && pwd == '123456'){
        data = {
          status: 0,
          data: {
            title: "個人中心",
            content: "歡迎進入個人中心"
          }
        }
      }else{
        data = {
          status: -1,
          data: {
            title: '登入失敗',
            content: "請輸入正確的賬號資訊"
          }
        }
      }
      return data
    }
  }
複製程式碼

修改 /controller/home.js 中的 indexregister 方法:

  const HomeService = require("../service/home")
  module.exports = {
    // 修改 index 方法
    index: async function (ctx, next) {
      await ctx.render("home/index", {title: "iKcamp歡迎您"})
    },
    // 修改 register 方法
    register: async function (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)
      }
    }
  }
複製程式碼

執行程式碼,並通過瀏覽器訪問 localhost:3000:

iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

點選進入戰場

iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

驗證失敗

iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

驗證成功

iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

目前,專案的基本功能都已完善。結構目錄如下:

  ├── 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
複製程式碼

在後面的章節中,我們將進一步完善其他功能,例如 JSON 資料傳遞,錯誤處理機制,日誌記錄功能等。

下一篇:提升篇 - 解析JSON——讓 Koa2 支援響應 JSON 資料

iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

上一篇:iKcamp新課程推出啦~~~~~iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 檢視Nunjucks

推薦: 翻譯專案Master的自述:

1. 乾貨|人人都是翻譯專案的Master

2. iKcamp出品微信小程式教學共5章16小節彙總(含視訊)


iKcamp|基於Koa2搭建Node.js實戰(含視訊)☞ 處理靜態資源

2019年,iKcamp原創新書《Koa與Node.js開發實戰》已在京東、天貓、亞馬遜、噹噹開售啦!

相關文章