博文原址:從服務器獲取數據,引入組件html
接着前面四篇:git
2.0版本以後組件會愈來愈重要。有關組件的介紹請看Ember.js 入門指南之二十八組件定義。組件的建立一樣可使用Ember CLI命令建立。以下命令建立了2個組件,建立的同時會自動建立2個文件;一個是組件類(app/components/xxx.js
)。一個是組件對應的模板(app/templates/components/xxx.hbs
)。github
ember g component library-item ember g component library-item-form
修改模板library-item數據庫
下面在組件模板library-item.hbs
中增長以下代碼:ubuntu
<!-- app/templates/components/library-item.hbs --> <div class="panel panel-default library-item"> <div class="panel-heading"> <h3 class="panel-title">{{item.name}}</h3> </div> <div class="panel-body"> <p>Address: {{item.address}}</p> <p>Phone: {{item.phone}}</p> </div> <div class="panel-footer text-right"> {{yield}} </div> </div>
若是注意看能夠發現上述代碼與app/templates/libraries/index.hbs
文件的代碼很是類似。這是item
替代了model
。至於item
是怎麼來的請看Ember.js 入門指南之二十九屬性傳遞,這篇博文介紹了組件的屬性傳遞,item
是從調用組件的模板傳遞過來的。上述代碼中還有一個重要的東西是{{yield}}
,這個表達式與{{outlet}}
相似。一樣也是一個佔位符。組件渲染以後會被傳進來的html代碼替換。好比下面的調用代碼:vim
{{#library-item item=model}} Closed {{/library-item}}
組件渲染以後,上述的Closed
會替換到{{yield}}
這裏,最終獲得的html代碼以下:api
<div class="panel-footer text-right"> Closed </div>
有關組件渲染的內容請看Ember.js 入門指南之三十包裹內容。服務器
修改模板library-item-formapp
<!-- app/templates/components/library-item-form.hbs --> <div class="form-horizontal"> <div class="form-group has-feedback {{if item.isValid 'has-success'}}"> <label class="col-sm-2 control-label">Name*</label> <div class="col-sm-10"> {{input type="text" value=item.name class="form-control" placeholder="The name of the Library"}} {{#if item.isValid}}<span class="glyphicon glyphicon-ok form-control-feedback"></span>{{/if}} </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">Address</label> <div class="col-sm-10"> {{input type="text" value=item.address class="form-control" placeholder="The address of the Library"}} </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">Phone</label> <div class="col-sm-10"> {{input type="text" value=item.phone class="form-control" placeholder="The phone number of the Library"}} </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default" {{action 'buttonClicked' item}} disabled="{{unless item.isValid 'disabled'}}">{{buttonLabel}}</button> </div> </div> </div>
注意觀察上述代碼與libraries/new.hbs
和libraries/edit.hbs
幾乎是同樣的。有點不同的是把校驗移到model
中。好比校驗name
屬性不爲空。
注意:頂部導入的代碼。less
import Model from 'ember-data/model'; import attr from 'ember-data/attr'; import Ember from 'ember'; export default Model.extend({ name: attr('string'), address: attr('string'), phone: attr('string'), isValid: Ember.computed.notEmpty('name') });
再修改app/templates/libraries/index.hbs
引入組件。
<h2>List</h2> <div class="row"> {{#each model as |library|}} <div class="col-md-4"> {{#library-item item=library}} {{#link-to 'libraries.edit' library.id class='btn btn-success btn-xs'}}Edit{{/link-to}} <button class="btn btn-danger btn-xs" {{action 'deleteLibrary' library}}>Delete</button> {{/library-item}} </div> {{/each}} </div>
在迭代中使用組件,經過屬性名item
傳遞迭代出來的對象library
到組件中。其中link-to
和button
這兩句代碼會替換到組件library-item
的{{yield}}
上。
等待項目重啓完成,能夠看到界面與以前的沒有任何變化。頁面是沒有變化,可是後臺的處理還須要完善。
修改app/templates/libraries/new.hbs
<!-- app/templates/libraries/new.hbs --> <h2>Add a new local Library</h2> <div class="row"> <div class="col-md-6"> {{library-item-form item=model buttonLabel='Add to library list' action='saveLibrary'}} </div> <div class="col-md-4"> {{#library-item item=model}} <br/> {{/library-item}} </div> </div>
修改app/templates/libraries/edit.hbs
<h2>Edit Library</h2> <div class="row"> <div class="col-md-6"> {{library-item-form item=model buttonLabel='Save changes' action='saveLibrary'}} </div> <div class="col-md-4"> {{#library-item item=model}} <br/> {{/library-item}} </div> </div>
在組件類library-item-form.js
增長對action
的處理。
import Ember from 'ember'; export default Ember.Component.extend({ buttonLabel: 'Save', actions: { buttonClicked(param) { this.sendAction('action', param); } } });
edit.hbs
和new.hbs
到form.hbs
原來的文件edit.hbs
和new.hbs
幾乎是同樣的,可使用組件重構。
<!-- /app/templates/libraries/form.hbs --> <h2>{{title}}</h2> <div class="row"> <div class="col-md-6"> {{library-item-form item=model buttonLabel=buttonLabel action='saveLibrary'}} </div> <div class="col-md-4"> {{#library-item item=model}} <br/> {{/library-item}} </div> </div>
爲了實現代碼複用,首先把不一樣的部分定義成屬性:title
、buttonLabel
。默認狀況下路由會渲染到同名的模板上,若是你想修改這個默認行爲可使用renderTemplate()
方法。
renderTemplate()
和setupController()
API介紹
默認狀況下路由會渲染到同名的模板上,咱們使用方法renderTemplate()
執行渲染的模板。好比下面的代碼使用這個方法執行路由new
渲染到模板libraries/form.hbs
。
// app/routes/libraries/new.js import Ember from 'ember'; export default Ember.Route.extend({ model: function () { return this.store.createRecord('library'); }, setupController: function (controller, model) { this._super(controller, model); controller.set('title', 'Create a new library'); controller.set('buttonLabel', 'Create'); }, renderTemplate() { this.render('libraries/form'); }, actions: { saveLibrary(newLibrary) { newLibrary.save().then(() => this.transitionTo('libraries')); }, willTransition() { let model = this.controller.get('model'); if (model.get('isNew')) { model.destroyRecord(); } } } });
注意方法setupController()
設置組件模板中的屬性title
和buttonLabel
的值。一樣的在修改路由edit.js
。
// app/routes/libraries/edit.js import Ember from 'ember'; export default Ember.Route.extend({ model(params) { return this.store.findRecord('library', params.library_id); }, setupController(controller, model) { this._super(controller, model); controller.set('title', 'Edit library'); controller.set('buttonLabel', 'Save changes'); }, renderTemplate() { this.render('libraries/form'); }, actions: { saveLibrary(newLibrary) { newLibrary.save().then(() => this.transitionTo('libraries')); }, willTransition(transition) { let model = this.controller.get('model'); if (model.get('hasDirtyAttributes')) { let confirmation = confirm("Your changes haven't saved yet. Would you like to leave this form?"); if (confirmation) { model.rollbackAttributes(); } else { transition.abort(); } } } } });
使用組件重構以後能夠刪除app/templates/libraries/new.hbs
和app/templates/libraries/edit.hbs
,這兩個文件不須要了。效果截圖以下:
nav-link-to
重構<li><a></a></li>
知道組件如何使用以後咱們繼續重構項目代碼,重構導航模板navbar.hbs
的連接代碼。使用Ember CLI命令建立組件。
ember g component nav-link-to
此次使用擴展的方式擴展一個組件類,擴展Ember內置的組件類LinkComponent
,使用方法extend()
擴展一個類。而後使用屬性tagName
指定渲染以後的標籤。更多有關組件屬性的介紹請看Ember.js 入門指南之三十一自定義包裹組件的HTML標籤,固然你也能夠參考網址的教程實現本文的需求。
// app/components/nav-link-to.js import Ember from 'ember'; export default Ember.LinkComponent.extend({ tagName: 'li' });
注意:記得修改Ember.Component.extend
爲Ember.LinkComponent.extend
。組件模板很簡單。
<!-- app/templates/components/nav-link-to.hbs --> <a href="">{{yield}}</a>
最後在修改導航模板navbar.hbs
爲以下內容:
<!-- app/templates/navbar.hbs --> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> {{#link-to 'index' class="navbar-brand"}}Library App{{/link-to}} </div> <div class="collapse navbar-collapse" id="main-navbar"> <ul class="nav navbar-nav"> {{#nav-link-to 'index'}}Home{{/nav-link-to}} {{#nav-link-to 'libraries'}}Libraries{{/nav-link-to}} {{#nav-link-to 'about'}}About{{/nav-link-to}} {{#nav-link-to 'contact'}}Contact{{/nav-link-to}} </ul> <ul class="nav navbar-nav navbar-right"> <li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a> <ul class="dropdown-menu"> {{#nav-link-to 'admin.invitation'}}Invitations{{/nav-link-to}} {{#nav-link-to 'admin.contact'}}Contacts{{/nav-link-to}} </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav>
等待項目重啓完成,能夠看到界面與以前的沒有任何變化,能夠任意點擊導航欄菜單且不會出錯。效果截圖以下:
本篇的家庭做業就是好好理解組件!參考下面的文章認真學習、理解組件。
爲了照顧懶人我把完整的代碼放在GitHub上,若有須要請參考參考。博文通過屢次修改,博文上的代碼與github代碼可能有出入,不過影響不大!若是你以爲博文對你有點用,請在github項目上給我點個star
吧。您的確定對我來講是最大的動力!!