Nodejs之MEAN棧開發(二)----視圖與模型


上一節做了對Express做了簡單的介紹,提出了controller,介紹了路由。這一節將重點放到視圖和模型上,完成幾個靜態頁面並部署到heroku上。

導航

前端布局使用bootstrap,從官網下載后置於public文件夾下。打開layout.jade 先做一個導航.

doctype html
html
  head
    meta(name='viewport', content='width=device-width, initial-scale=1.0')
    title= title
    link(rel='stylesheet', href='/bootstrap/css/bootstrap.css')
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    nav.navbar.navbar-default.navbar-fixed-top.navbar-inverse
     .container
      .navbar-header
        a.navbar-brand(href='/') ReadingClub

      .collapse.navbar-collapse
       ul.nav.navbar-nav.pull-right
         li
          a(href='/') 首頁
         li
          a(href='/Books') 讀物
         li
          a(href='/About') 關於
         li
          a(href='/Register') 注冊
         li
          a(href='/Login') 登錄
     #bodycontent.container
        block content

   footer.container
       .row
          .col-xs-12
            small © stoneniqiu 2016

    script(src='/javascripts/jquery-1.11.1.min.js')
    script(src='/bootstrap/js/bootstrap.min.js')

block content 上文有介紹,可以理解成一個占位符。因為現在還用不慣stylus,就直接寫css了,這樣vs還有智能提示。

style.css

body {
 font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
    background: gainsboro;
}
a {
  color: #00b7ff;
}
.navbar-default {
  background-color: #444;
  border-color: black;
}
.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus {
    color: #ffffff;
    background-color:#222;
}
.navbar-default .navbar-nav > li > a{
    color:  #ccc;
}
a.navbar-brand{color: #fff !important}
View Code

運行起來,看到導航條

如果訪問注冊和登錄,因為之前沒有設置相應的頁面就會報404。

出現這樣的頁面是因為在上文中,在app.js中有過設置
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

回頭看layout.jade 沒有一個html標簽,直接是元素名或者樣式名稱開始,這種寫法和sublime中寫html相似,屬性寫在括號里,文字內容用空格隔開。元素的嵌套關系 通過嚴格的縮進來控制,這樣的好處是代碼量更少,層次更分明,但是代碼一長,很不容易判斷縮進的准確位置,沒對齊很容易造成意外的嵌套。我現在的經驗是從左往右的編寫,而不是從上往下編寫。也就是說,用jade寫html的時候,先寫好最外層的元素,然后在逐步寫里面的子元素。而不是從上往下一個一個的寫,這樣就會出現縮進來帶的困擾。

模型與視圖

 回到home.js,我們用JavaScript建立一個books模型,包含title,info,rating,img和tags。因為還沒有使用數據庫,這里直接創建。

 books:

var books = [
{
    id: 0,
    title: "深入淺出Node.js",
    info: "朴靈 / 人民郵電出版社 / 2013-12-1 / CNY 69.00",
    rating: 5,
    img: "https://img3.doubanio.com/mpic/s27269296.jpg",
    tags: ["node", "深入淺出"],
    brief: '本書從不同的視角介紹了 Node 內在的特點和結構。由首章Node 介紹為索引,涉及Node 的各個方面,主要內容包含模塊機制的揭示、異步I/O 實現原理的展現、異步編程的探討、內存控制的介紹、二進制數據Buffer 的細節、Node 中的網絡編程基礎、Node 中的Web 開發、進程間的消息傳遞、Node 測試以及通過Node 構建產品需要的注意事項。最后的附錄介紹了Node 的安裝、調試、編碼規范和NPM 倉庫等事宜。本書適合想深入了解 Node 的人員閱讀。'
    ,ISBN: 9787115335500
    },
{
    id: 1,
    title: "程序員修煉之道 : 從小工到專家",
    info: "Andrew Hunt、David Thomas / 馬維達 / 電子工業出版社 / 2005-1 / 48.00元",
    rating: 5,
    img: "https://img3.doubanio.com/mpic/s3957863.jpg",
    tags: ["程序人生", "軟件開發"],
    brief: '《程序員修煉之道》由一系列的獨立的部分組成,涵蓋的主題從個人責任、職業發展,直到用於使代碼保持靈活、並且易於改編和復用的各種架構技術。利用許多富有娛樂性的奇聞軼事、有思想性的例子以及有趣的類比,全面闡釋了軟件開發的許多不同方面的最佳實踐和重大陷阱。無論你是初學者,是有經驗的程序員,還是軟件項目經理,本書都適合你閱讀。'
    ,ISBN: 9787505397194
    },
{
    id: 2,
    title: "Getting MEAN with Mongo, Express, Angular, and Node",
    info: "Simon Holmes / Manning Publications / 2015-11-26 / USD 44.99",
    rating: 4,
    img: "https://img3.doubanio.com/mpic/s27676844.jpg",
    tags: ["node", "web開發", "編程"],
    brief: 'MEAN棧開發,比較詳盡的的應用開發書籍'
    , ISBN: 9781617292033
    }
];
 res.render('books', { title: 'Books', books: books });

jade
模型其實就是一個json對象,接下來我們修改books頁面的布局。這里用左右布局,稍加調整
extends layout

block content 
  .row
   .col-md-9.page
     each book in books
       .row.booklist
         .col-md-2
          img(src='#{book.img}')
         .col-md-10
            p
             a(href="/Detail/#{book.id}")=book.title
            p=book.info
            p
            - for (var i = 1; i <= book.rating; i++)
                span.glyphicon.glyphicon-star
            - for (i = book.rating; i < 5; i++)
                span.glyphicon.glyphicon-star-empty

            p.tags
             each tag in book.tags
              span=tag

   .col-md-3
     .userinfo
       p stoneniqiu
View Code
 res.render('books', { title: 'Books', books: books });

在home.js中加入books,模型其實就是一個json對象,接下來我們修改books頁面的布局。這里用左右布局,稍加調整,

extends layout

block content 
  .row
   .col-md-9.page
     each book in books
       .row.booklist
         .col-md-2
          img(src='#{book.img}')
         .col-md-10
            p
             a(href="/Detail/#{book.id}")=book.title
            p=book.info
            p
            - for (var i = 1; i <= book.rating; i++)
                span.glyphicon.glyphicon-star - for (i = book.rating; i < 5; i++)
                span.glyphicon.glyphicon-star-empty

            p.tags
             each tag in book.tags
              span=tag

   .col-md-3
     .userinfo
       p stoneniqiu

得到效果:

 當然這些都還是靜態的,接下來介紹下jade引擎。jade是一個高性能的模板引擎,用於node。

 1.母版頁

 借助bootstrap的柵欄布局,分成左右兩部分。extends layout  表示引入layout母版頁,而layout中的block content 就會被當前頁面的block content中的內容替換掉。同樣可 以定義多個block

//- layout.jade
doctype html
html
  head
    block title
      title Default title
  body
    block content

引用頁面:

//- index.jade
extends layout

block title
  title Article Title

block content
  h1 My Article

生成的html:

<!doctype html>
<html>
  <head>
    <title>Article Title</title>
  </head>
  <body>
    <h1>My Article</h1>
  </body>
</html>

2.循環

each book in books

表示循環輸出模型,在Asp.net MVC的視圖中,需要先定義Model的類型。jade省掉了這個model,直接獲取模型的屬性。同樣也支持for循環,前面的‘-’號不可少。

- for (var i = 1; i <= book.rating; i++)
         span.glyphicon.glyphicon-star
- for (i = book.rating; i < 5; i++)
         span.glyphicon.glyphicon-star-empty

3.賦值

  空格賦值,這個空格不能少,不然jade會把ptext視為一個元素。空格后方都認為是字符串。

  p  text  輸出  <p>text<p>

所以如果是輸出變量,一定要用‘=’賦值。

  a(href="/Detail/")=book.title

 但如果是字符串組合輸入,應該用#{}

 img(src='#{book.img}')
  p  讀過#{book.title}  

 如果不想轉義內容 !{},- var 表示定義變量 ,相當於Razor中的@{}

- var riskyBusiness = "<em>Some of the girls are wearing my mother's clothing.</em>";
.quote
  p Joel: !{riskyBusiness}

輸出

<div class="quote">
  <p>Joel: <em>Some of the girls are wearing my mother's clothing.</em></p>
</div>

4.屬性

 如果是增加元素屬性,則更在元素后面的括號里完成

a(href="/Detail/")=book.title

輸出:

<a href="/Detail/">深入淺出Node.js</a>

如果是多個屬性用逗號隔開,也可以換行

a(class='button', href='google.com') 
input(
  type='checkbox'
  name='agreement'
  checked
)

還可以加入表達式

- var authenticated = true
body(class=authenticated ? 'authed' : 'anon')

而Razor要在元素里面寫表達式就有點丑陋。

@{
    var ischeck = true;
}
<input type="checkbox" @if (ischeck)
                       {
                           @Html.Raw("class='selected'")
                       }              
    />

5.子視圖 

這里用子視圖還不太准確,我們已經知道通過extends 和 block 來引入母版頁,並按模塊取代內容。而子視圖主要是強調復用,是嵌入到別的視圖文件中。jade是用mixin(混合)定義一個部分視圖,用‘+’使用 例如:

mixin list
  ul
    li foo
    li bar
    li baz
 
       +list
       +list

輸出

比如把頁面上顯示星星的部分提出來,在view文件夾下建一個_include文件夾,並創建一個rating.jade文件:

mixin outputRating(rating)
  - for (var i = 1; i <= rating; i++)
    span.glyphicon.glyphicon-star
  - for (i = rating; i < 5; i++)
    span.glyphicon.glyphicon-star-empty

這樣在頁面上引用

include _includes/rating

然后在指定位置輸出,主要有‘+’號。

 p
    +outputRating(book.rating)
這里的mixin就相當於是一個JavaScript函數,可以傳遞多個參數。 更多內容可以移步  http://jade-lang.com/ jade官網。

同理創建了detail.jade 和index.jade

detail.jade

extends layout
include _includes/rating

block content
  .row
   .col-md-9.page.bookdetail
     h3=book.title
     .row
      .col-md-2
           img(src='#{book.img}')
      .col-md-10
            p=book.info
            p
             +outputRating(book.rating)
            p.tags
             each tag in book.tags
              span=tag
            p ISBN:#{book.ISBN}
     h3 內容簡介
     p.brief=book.brief    
   .col-md-3
     .userinfo
       p stoneniqiu 
View Code

index.jade

extends layout

block content 
  .row
   .col-md-9.page
     .row.topictype
       a.label.label-info(href='/')  全部
       a(href='/') 讀書
       a(href='/') 書評
       a(href='/') 求書
       a(href='/') 求索
     each topic in topics
       .row.topiclist
         img(src='#{topic.img}')
         span.count
            i.coment=topic.commentCount
            i /
            i=topic.visitedCount

         span.label.label-info=topic.type
         a(href='/')=topic.title

         span.pull-right=topic.postTime
         a.pull-right.author(href='/')=topic.author

   .col-md-3
     .userinfo
       p stoneniqiu
View Code

至此,我們創建了三個靜態頁面,基本熟悉了jade語法。當然jade不止這些,后期隨着項目的深入再不斷的探索。

部署:

目前我已經將代碼提交到github上,然后部署在heroku上。

github:https://github.com/stoneniqiu/ReadingClub 有興趣的朋友可以一起開發學習。

觀摩請戳https://stoneniqiu-mean.herokuapp.com/ 

heroku提供了三百兆的免費空間,還有個規則的域名,如何部署請移步:三步將Node應用部署到Heroku上

小結:這一節主要是學習了jade引擎,目前的數據模型就是json對象。對比Asp.net MVC的Razor引擎,元素輸出和子視圖區各有千秋。jade的代碼量更少,用縮進處理嵌套,子視圖就相當於是@Html.Partial()。 目前網站都還是靜態的,下一節將介紹mongodb和mongoose,實現對數據的操作,讓頁面動態化。

 jade官網:http://jade-lang.com/

 jade開源:https://github.com/jadejs/jade 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM