視頻地址:https://www.cctalk.com/v/15114923882788javascript
無非花開花落,靜靜。css
這裏咱們使用第三方中間件: koa-static
html
安裝 koa-static
:前端
npm i koa-static -S
修改 app.js
,增長並指定 /public
目錄爲靜態資源目錄。java
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') })
以後咱們對項目的視圖進行美化,使之更爲賞心悅目。git
在 /public/home/
目錄下新增樣式文件 main.css
,內容以下:github
*{ 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
視圖文件,按照繼承的方式提取出公用部分。web
新建 /views/common/header.html
npm
<header class="header"> <div class="header-box wraper">Node實戰教程 | <span class="logo">© iKcamp</span></div> </header>
新建 /views/common/footer.html
json
<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
交互頁面。此時咱們對登陸功能的視圖進行美化,有主頁,登陸,以及登陸後的響應頁面。
新增 /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
的處理邏輯進行修改
修改 /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
中的 index
和 register
方法:
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
:
點擊進入戰場
驗證失敗
驗證成功
目前,項目的基本功能都已完善。結構目錄以下:
├── 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新課程推出啦~~~~~iKcamp|基於Koa2搭建Node.js實戰(含視頻)☞ 視圖Nunjucks