带有响应式网页设计的MEAN和UGLI CRUD
現在您已經熟悉了MEAN應用程序的機制,是時候開始定制在本系列的第一部分中創建并在第二部分中瀏覽的MEAN.JS應用程序了。 在第三部分中,我將演示該應用程序的基本CRUD功能。 您還將學到一些有關響應式Web設計和Bootstrap的知識。
您將在本系列其余部分中構建的應用程序被親切地稱為UGLI:“用戶組列表和信息”應用程序。 自2010年以來,我一直在運行HTML5丹佛用戶組(之前是Boulder Java用戶組,在那之前是丹佛Java用戶組),所以我是本地用戶組的忠實支持者也就不足為奇了。 讓我感到驚訝的是,缺少運行用戶組的專用軟件。 (是皮鞋匠的孩子總是赤腳,對嗎?)現在是時候解決這個問題了。
許多用戶組在Meetup.com上找到了在線主頁。 我使用MEAN和UGLI應用程序的目標不是替換Meetup.com。 相反,我想與它進行深度整合。 Meetup.com在運行一個成功的用戶組所需的大多數核心功能上都表現出色:注冊新用戶,發布會議詳細信息,處理RSVP等。 但是,用戶組負責人仍然缺少一些關鍵功能,包括管理演示者列表以及鏈接到幻燈片。 UGLI將填補空白。 (請參閱下載以獲取完整的示例代碼。)
調整品牌
關于本系列
MEAN(MongoDB,Express,AngularJS,Node.js)堆棧是長期流行的LAMP堆棧的現代挑戰者,用于使用開源軟件構建專業網站。 MEAN代表了體系結構和思維模型的重大轉變-從關系數據庫到NoSQL,從服務器端的Model-View-Controller到客戶端的單頁應用程序。 在本系列中,將學習MEAN堆棧的技術如何相互補充,以及如何使用該堆棧來創建二十一世紀的現代全堆棧JavaScript Web應用程序。
使應用程序UGLI的首要任務是調整應用程序的品牌。 需要在應用程序的服務器端的config和app目錄中進行一些更改。 其他要求在客戶端的公共目錄中。
從存儲在config / env / all.js中的元數據開始。 將標題更改為HTML5 Denver(或您選擇的用戶組),并將描述更改為HTML5 Denver用戶組,如清單1所示。
清單1. config / env / all.js
'use strict';module.exports = {app: {title: 'HTML5 Denver',description: 'HTML5 Denver User Group',keywords: 'MongoDB, Express, AngularJS, Node.js'},config / env / development.js中的標題也需要更改,如清單2所示。如您上次了解的那樣,development.js和all.js在運行時合并。
清單2. config / env / development.js
'use strict';module.exports = {db: 'mongodb://localhost/test-dev',app: {title: 'HTML5 Denver'},接下來,更改顯示在導航欄左上角的品牌。 為此,請編輯public / modules / core / views / header.client.view.html。 在第9行附近找到帶有navbar-brand類的anchor標簽,并將正文更改為HTML5 Denver ,如清單3所示。
清單3. public / modules / core / views / header.client.view.html
<div class="container" data-ng-controller="HeaderController"><div class="navbar-header"><button class="navbar-toggle" type="button" data-ng-click="toggleCollapsibleMenu()"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="/#!/" class="navbar-brand">HTML5 Denver</a></div><!-- ...snip... --> </div>要驗證您的更改,請在命令行中輸入mongod啟動MongoDB,然后通過輸入grunt啟動您的應用程序。 在瀏覽器中查看網絡應用,以在菜單和標題欄中查看您的品牌。
要完成品牌更改,您需要替換顯示在主頁正文中的public / modules / core / views / home.client.view.html中的樣板文本。 創建一個名為home.client.view.html.original的副本,以便以后可以參考(如果需要)。
該文件使用Bootstrap框架的功能來確保您的網站從一開始就可用于移動設備。 在繼續之前,熟悉Bootstrap提供的12列網格布局很有幫助。
了解Bootstrap和響應式Web設計
查看任何印刷版報紙或雜志,您會看到正在使用的列。 有時,圖像或標題對于某種設計風格而言跨越一欄以上,但是基本的柱狀布局是幾乎所有打印頁面的基礎。
網頁沒有什么不同。 例如,訪問TIME網站。 您最初會看到基于列的布局。 但是請注意,將瀏覽器窗口的寬度從全屏減小到極窄時會發生什么。 當您縮小窗口時,可見列的數量會減少,而當您增大窗口時,可見列的數量會增加。
為什么要12列?
因為我們是10個手指的物種,所以以10為底的十進制數字系統似乎很自然。 如果您已經在CSS中創建了自定義顏色,則可能對16進制的十六進制數字一無所知。 那么,為什么Twitter的布局選擇12列而不是10列或16列? 因為12可以被2、3、4和6整除,所以將布局分為一半,三分之一,第四和第六(以及第十二和一欄)是微不足道的。 自古巴比倫人,羅馬人,中國人和其他人以來,Base-12十二進制數字系統已被廣泛使用。 這就是為什么我們一天有12(或24)小時,一年有12個月,英尺只有12英寸。 用拇指輕拍被關節分開的手指部分(就像巴比倫人所做的那樣),一方面可以計數到12,并使十二進制的Bootstrap數學更容易可視化。
此效果稱為響應式網頁設計 ,因為網頁會響應該網頁并將其設計調整為請求該網頁的設備的屏幕尺寸。 現代化的Web開發人員可以構建從最小的手持設備到坐在桌子上或掛在墻上的最大屏幕的無縫網站。 積極地為智能手機,平板電腦,筆記本電腦等創建單獨的離散網站,并使用單獨的http://m.*和http://www.* URL,這是20世紀的一種過時策略。
自適應網頁設計不是萬能的策略; 而是一種“在所有設備上外觀和感覺都不錯的網站”策略。 您不必選擇用戶使用哪種設備來訪問您的網站,因此至關重要的是,您的設計必須具有內置的靈活性以進行相應的調整。
與傳統計算機相比,移動設備訪問許多受歡迎的網站(包括Facebook和Instagram)的頻率更高。 Twitter的用戶群主要是移動用戶。 Twitter規范了其響應式Web設計策略,并將其作為Bootstrap開源。 Bootstrap具有12列的布局,該布局可以根據用于定義列CSS類而增大或縮小。
請注意MEAN.JS示例應用程序主頁上的MongoDB,Express,AngularJS和Node.js的四列,如圖1所示。
圖1. Bootstrap的列式布局示例
現在查看清單4所示的public / modules / core / views / home.client.view.html的源代碼,以查看Bootstrap的12列布局在起作用。
清單4. public / modules / core / views / home.client.view.html
<div class="row"><div class="col-md-3"><h2><strong>M</strong>ongoDB</h2></div><div class="col-md-3"><h2><strong>E</strong>xpress</h2></div><div class="col-md-3"><h2><strong>A</strong>ngularJS</h2></div><div class="col-md-3"><h2><strong>N</strong>ode.js</h2></div> </div>如果將class="row"添加到父div ,則可以將class="col- xx - N "屬性添加到子div以將它們劃分為列。 N值必須是1到12之間的數字,并且xx值取決于您要針對以下哪個設備優化布局的大小:
- xs適用于超小型設備(寬度小于768像素)
- 小型裝置的sm (768至991像素)
- 適用于中型設備的md (介于992和1,199像素之間)
- lg適用于大型設備(1200像素或更大)
有關更多信息,請參見Bootstrap CSS文檔的“ 網格系統”部分。
因為清單4中的每一列都針對中型( md )設備進行了優化,所以如果您在屏幕寬度小于992像素的設備上訪問此頁面,則這些列將垂直堆疊而不是水平堆疊。 使瀏覽器窗口足夠窄以觸發此更改,如圖2所示。
圖2.移動設備上的響應式Web設計示例
現在,使用您到目前為止所學的知識,是時候用一些UGLI特定的文本替換home.client.view.html中的樣板文本。
首先,從W3C HTML5徽標頁面下載256像素HTML5徽標,然后將其復制到public / modules / core / img / brand / HTML5_Logo_256.png。 然后用清單5中的源替換public / modules / core / views / home.client.view.html中的現有HTML。
清單5. public / modules / core / views / home.client.view.html
<section data-ng-controller="HomeController"><div class="jumbotron text-center"><div class="row"><div class="col-md-4"><img alt="HTML5" class="img-responsive center-block" src="modules/core/img/brand/HTML5_Logo_256.png" /></div><div class="col-md-8"><h1>The HTML story is still being written.</h1> <h2><em>Come hear the latest chapter at the HTML5 Denver User Group.</em></h2></div></div></div> </section>當您在寬瀏覽器窗口中查看網站時,HTML5徽標會出現在文本旁邊,如圖3所示。
圖3.新的UGLI主頁
當您使瀏覽器窗口足夠狹窄時,徽標會堆疊在文本的頂部,如圖4所示。
圖4.新的UGLI主頁,它將出現在移動設備上
看到使用Bootstrap使您的網站適合移動設備的操作有多么容易? Bootstrap是我為客戶建立的每個新網站的基礎。
現在是時候解決MEAN堆棧中的CRUD了。
基本增刪改查
Meetup.com在幫助我管理用戶組事件方面做得很好。 但是在事件過去之后,事件的時間方面并不像當晚發生的談話那么重要。
換句話說,該網站的一個用戶故事是:“下次會議將要討論什么?” 最初的Meetup.com對此用戶故事非常滿意。
我希望通過UGLI應用程序解決的第二個用戶故事“向我展示與MEAN堆棧相關的所有討論,無論它們何時發生”。 要實現這個故事,您必須圍繞一個名為Talk的新模型對象創建一個CRUD基礎結構。 值得慶幸的是,可以使用Yeoman生成器來幫助建立該基礎結構。
在應用程序的根目錄中,輸入yo meanjs:crud-module talks 。 根據提示:
清單6顯示了交互式命令行序列。
清單6.使用Yeoman生成器生成新的CRUD模塊
$ yo meanjs:crud-module talks [?] Which supplemental folders would you like to include in your angular module? css, img, directives, filters [?] Would you like to add the CRUD module links to a menu? Yes [?] What is your menu identifier? topbarcreate app/controllers/talks.server.controller.jscreate app/models/talk.server.model.jscreate app/routes/talks.server.routes.jscreate app/tests/talk.server.model.test.jscreate public/modules/talks/config/talks.client.routes.jscreate public/modules/talks/controllers/talks.client.controller.jscreate public/modules/talks/services/talks.client.service.jscreate public/modules/talks/tests/talks.client.controller.test.jscreate public/modules/talks/config/talks.client.config.jscreate public/modules/talks/views/create-talk.client.view.htmlcreate public/modules/talks/views/edit-talk.client.view.htmlcreate public/modules/talks/views/list-talks.client.view.htmlcreate public/modules/talks/views/view-talk.client.view.htmlcreate public/modules/talks/talks.client.module.js注意,在清單6中,生成器創建了所需的服務器端基礎結構(存儲在app目錄中):路由,控制器,模型和單元測試。 它還在public / modules / talks目錄下構建了所有客戶端工件。
稍后,您將向Talk對象添加一些自定義字段。 在執行此操作之前,請通過在瀏覽器中訪問網站來查看默認情況。
點擊右上角和類型的登入鏈接的用戶名和密碼在本系列前面創建,或點擊注冊并創建一個新的證書。
登錄后,您可以在左上方看到“ 對話”菜單。 從菜單中選擇New Talk ,以打開一個HTML表單,該表單提供一個孤獨的Name字段,如圖5所示。
圖5.定制之前的New Talk表單
這是一個很好的開始,但是您需要的不僅僅是一個簡單的文本字段,以捕獲Talk所有屬性。
添加新字段以保持持久性
要將新字段添加到Talk ,必須編輯六個文件-四個用于顯示,兩個用于持久性:
- app / models / talk.server.model.js
- 公共/模塊/控制器/talks.client.controller.js
- public / modules / talks / views / create-talk.client.view.html
- public / modules / talks / views / edit-talk.client.view.html
- public / modules / talks / views / view-talk.client.view.html
- public / modules / talks / views / list-talks.client.view.html
我將首先解決持久性問題。 解決方案的一半在服務器端,另一半在客戶端。
服務器端模型(在app / models / talk.server.model.js中定義)是應用程序真實性的來源。 在其中,您將為字段命名,提供數據類型,添加驗證規則,等等。
客戶端控制器(在public / modules / controllers / talks.client.controller.js中定義)收集來自用戶的數據輸入,并通過HTTP請求將數據推送到服務器。 控制器還通過線路提取JSON數據,并將其交給視圖進行展示。
這種架構有趣的是,模型對象永遠不會離開服務器。 相反,對象是從客戶端發送的數據中實現的,并在HTTP響應中序列化為JSON。
該應用程序有兩個控制器-一個在服務器端,另一個在客戶端-但是只有客戶端控制器才有意義。 服務器端控制器只需將傳入的JSON倒入模型對象中,因此在向模型中添加其他字段時,無需對服務器端控制器進行任何調整。 客戶端控制器需要進行一些調整以適應新字段。
打開app / models / talk.server.model.js,向服務器端模型添加新字段,如清單7所示。您可以看到在另外兩個元數據字段旁邊定義的期望name字段( 如圖5所示): created和user 。
清單7. app / models / talk.server.model.js
/*** Talk Schema*/ var TalkSchema = new Schema({name: {type: String,default: '',required: 'Please fill Talk name',trim: true},created: {type: Date,default: Date.now},user: {type: Schema.ObjectId,ref: 'User'} });基于JSON的架構是不言自明的。 定義新字段時,可以指定數據類型,默認值,要顯示的必填字段的錯誤消息以及許多其他改進。 有關更多信息,請參見Mongoose文檔 。
為description , presenter和slidesUrl添加新字段,如清單8所示。在這種情況下, description和presenter都是必填字段。 slidesUrl字段是可選的。
清單8. app / models / talk.server.model.js
/*** Talk Schema*/ var TalkSchema = new Schema({name: {type: String,default: '',required: 'Please fill Talk name',trim: true},description: {type: String,default: '',required: 'Please fill Talk description',trim: true}, presenter: {type: String,default: '',required: 'Please fill Talk presenter',trim: true},slidesUrl: {type: String,default: '',trim: true},created: {type: Date,default: Date.now},user: {type: Schema.ObjectId,ref: 'User'} });此時,您的服務器端后端已準備就緒,可以接受新字段。 現在,您需要解決客戶端控制器。 打開public / modules / controllers / talks.client.controller.js并添加新字段,如清單9所示。
清單9. public / modules / controllers / talks.client.controller.js
// Create new Talk $scope.create = function() {// Create new Talk objectvar talk = new Talks ({name: this.name,description: this.description,presenter: this.presenter,slidesUrl: this.slidesUrl});// Redirect after savetalk.$save(function(response) {$location.path('talks/' + response._id);}, function(errorResponse) {$scope.error = errorResponse.data.message;});// Clear form fieldsthis.name = '';this.description = '';this.presenter = '';this.slidesUrl = ''; };$scope.create函數是將表單字段聚合到JSON對象中的地方,然后將其發送到服務器進行持久化。 在將模型中的相應字段添加到控制器后,您將獲得故事的持久性部分。
現在是時候將重點轉移到表示層了,以便您的用戶可以查看新字段并與之交互。
添加新字段以顯示
查看public / modules / talks / views /。 其中有四個文件與CRUD生命周期有關:
- create-talk.client.view.html
- edit-talk.client.view.html
- view-talk.client.view.html
- list-talks.client.view.html
打開create-talk.client.view.html,如清單10所示。
清單10.生成的create-talk.client.view.html
<section data-ng-controller="TalksController"><div class="page-header"><h1>New Talk</h1></div><div class="col-md-12"><form class="form-horizontal" data-ng-submit="create()" novalidate><fieldset><div class="form-group"><label class="control-label" for="name">Name</label><div class="controls"><input type="text" data-ng-model="name" id="name" class="form-control" placeholder="Name" required></div></div><div class="form-group"><input type="submit" class="btn btn-default"></div><div data-ng-show="error" class="text-danger"><strong data-ng-bind="error"></strong></div></fieldset></form></div> </section>復制與Name字段相關的代碼塊三遍,以支持Description , Presenter和slidesUrl ,如清單11所示。請注意,我將Description字段設置為textarea而不是簡單的文本字段。 另外,我從slidesUrl字段中刪除了required屬性,并將input type從text更改為url 。
清單11.更新的create-talk.client.view.html
<section data-ng-controller="TalksController"><div class="page-header"><h1>New Talk</h1></div><div class="col-md-12"><form class="form-horizontal" data-ng-submit="create()" novalidate><fieldset><div class="form-group"><label class="control-label" for="name">Name</label><div class="controls"><input type="text" data-ng-model="name" id="name" class="form-control" placeholder="Name" required></div></div><div class="form-group"><label class="control-label" for="description">Description</label><div class="controls"><textarea data-ng-model="description" id="description" class="form-control" placeholder="Description" required></textarea></div></div><div class="form-group"><label class="control-label" for="presenter">Presenter</label><div class="controls"><input type="text" data-ng-model="presenter" id="presenter" class="form-control" placeholder="Presenter" required></div></div><div class="form-group"><label class="control-label" for="slidesUrl">Slides</label><div class="controls"><input type="url" data-ng-model="slidesUrl" id="slidesUrl" class="form-control" placeholder="Slides Url"></div></div> <div class="form-group"><input type="submit" class="btn btn-default"></div><div data-ng-show="error" class="text-danger"><strong data-ng-bind="error"></strong></div></fieldset></form></div> </section>在Web瀏覽器中,新修改的New Talk頁面如圖6所示。
圖6.定制后的New Talk表單
當您對更改感到滿意時,請打開edit-talk.client.view.html并在那里進行相應的更改,如清單12所示。
清單12. edit-talk.client.view.html
<div class="col-md-12"><form class="form-horizontal" data-ng-submit="update()" novalidate><fieldset><div class="form-group"><label class="control-label" for="name">Name</label><div class="controls"><input type="text" data-ng-model="talk.name" id="name" class="form-control" placeholder="Name" required></div></div><div class="form-group"><label class="control-label" for="description">Description</label><div class="controls"><textarea data-ng-model="talk.description" id="description" class="form-control" placeholder="Description" required></textarea></div></div><div class="form-group"><label class="control-label" for="presenter">Presenter</label><div class="controls"><input type="text" data-ng-model="talk.presenter" id="name" class="form-control" placeholder="Presenter" required></div></div><div class="form-group"><label class="control-label" for="slidesUrl">Slides</label><div class="controls"><input type="url" data-ng-model="talk.slidesUrl" id="name" class="form-control" placeholder="Slides Url"></div></div><div class="form-group"><input type="submit" value="Update" class="btn btn-default"></div><div data-ng-show="error" class="text-danger"><strong data-ng-bind="error"></strong></div></fieldset></form> </div>請注意,用于編輯HTML與您之前修改的創建表單略有不同。 編輯時,您已經有一個Talk對象,因此data-ng-model屬性以完全限定的方式引用字段,例如talk.name而不是name 。 在Web瀏覽器中查看您的更改,如圖7所示。
圖7.定制后的Edit Talk表單
view-talk.client.view.html頁面是對象的只讀視圖。 用戶在保存新的Talk ,更新現有的Talk或從列表頁面中選擇Talk后,可以在此視圖中進行登陸。 進行清單13所示的更改。
清單13. edit-talk.client.view.html
<div class="page-header"><h1 data-ng-bind="talk.name"></h1><h2><em>by {{talk.presenter}} <span ng-if="talk.slidesUrl !== '' ">[<a href="{{talk.slidesUrl}}">slides</a>]</span></em></h2><p>{{talk.description}}</p> </div>回想一下slidesUrl字段是可選的。 在視圖頁面中,您正在使用ng-if指令(如果已填充)有條件地顯示該字段。 通過在瀏覽器中查看頁面來驗證此行為,如圖8所示。
圖8.定制后的View Talk表單
您需要調整的最后一個視圖是列表視圖。 打開list-talks.client.view.html并進行清單14所示的調整。
清單14. list-talks.client.view.html
<div class="list-group"><a data-ng-repeat="talk in talks" data-ng-href="#!/talks/{{talk._id}}" class="list-group-item"><h4 class="list-group-item-heading" data-ng-bind="talk.name"></h4><p><em>by {{talk.presenter}}</em></p></a> </div>請注意, data-ng-repeat指令用于顯示從服務器返回的對話列表中的每個對話。 在瀏覽器中查看結果,如圖9所示。
圖9.定制后的List Talks表單
結論
此時,您已經對MEAN堆棧的各個部分之間的交互方式有了很好的了解。 您正在使用Bootstrap的自適應Web設計功能來確保您的網站在所有設備上看起來都不錯,而不僅僅是具有101鍵和鼠標的傳統設備。 您已經體驗了使用Yeoman生成器向您的應用程序添加新的CRUD模塊的強大功能和便捷性。 生成器將所有原始工件放在正確的目錄中,從而使您可以輕松地定制它們。
在下一期中,您將看到將來自遠程源的數據合并到您的應用程序中是多么容易。 具體來說,您將開始直接通過Meetup的RESTful API從Meetup.com提取事件數據。 在此之前,請盡情掌握MEAN。
翻譯自: https://www.ibm.com/developerworks/opensource/library/wa-mean3/index.html
總結
以上是生活随笔為你收集整理的带有响应式网页设计的MEAN和UGLI CRUD的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机领域中的牛人,计算机视觉领域的牛人
- 下一篇: npm 报错:line 1: rimra