Ember.js 入門指南——{{link-to}} 助手
1,link-to助手常規使用
link-to助手錶達式渲染之後就是一個a標籤。而a標籤的href屬性的值是根據路由生成的,與路由的設定是息息相關的。並且每個設定的路由名稱都是有著對應的關係的。
為了演示效果,用命令生成了一個route(或者手動建立檔案)並獲取測試資料。本文結合路由設定,隨便串講了一些路由方面的知識,如果你能看懂最好了,看不懂也不要緊後面會有一整章介紹路由。
1,增加子路由
// app/routers.js import Ember from 'ember'; import config from './config/environment'; var Router = Ember.Router.extend({ location: config.locationType }); Router.map(function() { this.route('posts', function() { this.route('detail', {path: '/:post_id'}); //指定子路由,:post_id會自動轉換為資料的id }); }); export default Router;
如上述程式碼,在posts下增加一個子路由detail。並且指定路由名為“/:post_id”,“:post_id”是一個動態欄位,一般情況下預設為model的id屬性。經過模板渲染之後會得到類似於“posts/1”、“posts/2”這種形式的路由。
2,在route初始化資料
// app/routes/posts.js import Ember from 'ember'; export default Ember.Route.extend({ model: function() { return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/pulls'); } });
使用Ember提供的方法直接從遠端獲取測試資料。測試資料的格式可以用瀏覽器直接開啟上面的URL就可以看到。
3,新增顯示的模板
<!-- // app/templates/posts.hbs --> <div> <div> <div class="col-md-10 col-xs-10"> <div style="margin-top: 70px;"> <ul> {{#each model as |item|}} <li> <!--設定路由,路由的層級與router.js裡定義的要一致 --> {{#link-to 'posts.detail' item}} {{item.title}} {{/link-to}} </li> {{/each}} </ul> </div> </div> </div> </div>
直接用{{#each}}遍歷出所有的資料,並顯示在介面上,由於資料比較多可能顯示的比較慢,特別是頁面重新整理之後看到一片空白,請不要急著重新整理頁面,等待一下即可……。下圖是結果的一部分:
我們檢視頁面的原始碼,可以看到link-to助手渲染之後的HTML程式碼,自動生成了URL,在router.js裡配置的post_id渲染之後都被model的id屬性值代替了。
如果你沒有測試資料,你還可直接把link-to助手的post_id寫死,可以直接把資料的id值設定到link-to助手上。在模板檔案的ul標籤下一行增加如下程式碼,在link-to助手中指定id為1:
<!-- 增加一條直接指定id的資料 -->
<li>
{{#link-to 'posts.detail' 1}}增加一條直接指定id的資料{{/link-to}}
</li>
渲染之後的HTML程式碼為
<li>
<a id="ember404" href="/posts/1">增加一條直接指定id的資料
</a>
</li>
可以看到與前面使用動態資料渲染之後的href的格式是一樣的。如果你想設定某個a標籤是啟用狀態,你可以直接在標籤上增加一個CSS類(class=”active”)。
2,link-to助手設定多個動態欄位
開發中,路由的路徑經常不是2層的(post/1)也有可能是多層次的(post/1/comment、post/1/2或者post/1/comment/2等等形式。),如果是這種形式的URL在link-to助手上又要怎麼去定義呢?
老樣子,在演示模板之前還是需要先構建好測試資料以及修改對應的路由設定,此時的路由設定是多層的,因為link-to助手渲染之後得到的href屬性值就是根據路由生成的!!!這個必須要記得……
1,一個路由下有個多子路由
// app/routers.js
import Ember from 'ember';
import config from './config/environment';
var Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
// this.route('handlebarsConditionsExpRoute');
// this.route('handlebars-each');
// this.route('store-categories');
// this.route('binding-element-attributes');
// link-to例項理由配置
// this.route('link-to-helper-example', function() {
// this.route('edit', {path: '/:link-to-helper-example_id'});
// });
this.route('posts', function() {
//指定子路由,:post_id會自動轉換為資料的id
this.route('detail', {path: '/:post_id'}, function() {
//增加一個comments路由
this.route('comments');
// 第二個子路由comment,並且路由是個動態欄位comment_id
this.route('comment', {path: '/:comment_id'});
});
});
});
export default Router;
如果是上述配置,渲染之後得到的路由格式posts/detail/comments。由於獲取遠端資料比較慢直接註釋掉posts.js裡的model回撥方法,就直接使用寫死id的方式。
注意:上述配置中,在路由detail下有2個子路由,一個是comments,一個是comment,並且這個是一個動態段。由此模板渲染之後應該是有2種形式的URL。一種是posts.detail.comments(posts/1/comments),另一種是posts.detail.comment(posts/1/2)。如果能理解這個那route巢狀層次再多應該也能看明白了!
<!-- // app/templates/posts.hbs -->
<div>
<div>
<div class="col-md-10 col-xs-10">
<div style="margin-top: 70px;">
<ul>
<!-- 增加一條直接指定id的資料 -->
<li>
<!—- 注意此時只有一個動態段,所以只有一個數字1,Ember會根據順序自動匹配到動態段的位置上。 -->
{{#link-to 'posts.detail.comments' 1}}
posts.detail.comments(posts/1/comments)形式
{{/link-to}}
</li>
<li>
<!—-
注意此時有2個動態段,所以有2個數字1,2,Ember會根據順序自動匹配到動態段的位置上。
第一個數字1會匹配到第一個動態段post_id上,第二個數字2會匹配到動態段comment_id上
-->
{{#link-to 'posts.detail.comment' 1 2}}
posts.detail.comment(posts/1/2)形式
{{/link-to}}
</li>
</ul>
</div>
</div>
</div>
</div>
渲染之後的html結果如下:
如果是動態段的一般都是model的id代替,如果不是動態段的直接顯示配置的路由名稱。
2,多層路由巢狀
上面演示了多個子路由的情況,下面接著介紹一個路由有多個層次,並且是有個多個動態段和非動態段組成的情況。
首先修改路由配置,把comments設定為detail的子路由。並且在comments下在設定一個動態段的子路由comment_id。
// app/routers.js import Ember from 'ember'; import config from './config/environment'; var Router = Ember.Router.extend({ location: config.locationType }); Router.map(function() { this.route('posts', function() { //指定子路由,:post_id會自動轉換為資料的id this.route('detail', {path: '/:post_id'}, function() { //增加一個comments路由 this.route('comments', function() { // 在comments下面再增加一個子路由comment,並且路由是個動態欄位comment_id this.route('comment', {path: '/:comment_id'}); }); }); }); }); export default Router;
模板使用路由的方式posts.detail.comments.comment。正常情況應該生成類似posts/1/comments/2這種格式的URL。
<!-- // app/templates/posts.hbs -->
<div>
<div>
<div class="col-md-10 col-xs-10">
<div style="margin-top: 70px;">
<ul>
<li>
<!--
一共設定了4層路由
-->
{{#link-to 'posts.detail.comments.comment' 1 2}}
posts.detail.comments.comment(posts/1/comments/2)形式
{{/link-to}}
</li>
</ul>
</div>
</div>
</div>
</div>
渲染之後得到的HTML如下:
<ul>
<li>
<!-- 一共設定了4層路由 -->
<a id="ember473" href="/posts/1/comments/2" class="active ember-view"> posts.detail.comments.comment(posts/1/comments/2)形式
</a>
</li>
</ul>
結果正如我們預想的組成了4層路由(/posts/1/comment/2)。
補充內容。
對於上述第二點多層路由巢狀的情況你還可以使用下面的方式設定路由和模板,並且可用同時設定了/posts/1/comments和/posts/1/comments/2。
this.route('posts', function() { //指定子路由,:post_id會自動轉換為資料的id this.route('detail', {path: '/:post_id'}, function() { //增加一個comments路由 this.route('comments'); // 注意區分與前面的設定方式,comment渲染之後直接被comments/:comment_id替換了,會得到如posts/1/comments/2這種形式的URL this.route('comment', {path: 'comments/:comment_id'}); }); });
<!-- // app/templates/posts.hbs -->
<div>
<div>
<div class="col-md-10 col-xs-10">
<div style="margin-top: 70px;">
<ul>
<li>
<-- 設定的方式不變 -->
{{#link-to 'posts.detail.comments' 1}}
posts.detail.comments(/posts/1/comments)形式
{{/link-to}}
</li>
<li>
<!--
一共設定了4層路由,與前面的設定方式一樣
-->
{{#link-to 'posts.detail.comment' 1 2}}
posts.detail.comments.comment(posts/1/comments/2)形式
{{/link-to}}
</li>
</ul>
</div>
</div>
</div>
</div>
渲染之後的HTML結果如下:
兩種方式定義的路由渲染的結果是一樣的,看個人喜歡了,定義方式也是非常靈活的。第一種定義方式看著比較清晰,看程式碼就知道是一層層的。但是需要寫更多程式碼。第二種定義方式更加簡潔,不過看不出巢狀的層次。
對於上述route的設定如果還不能理解也不要緊,後面會有一整章是介紹路由的,然而你能結合link-to助手理解了路由設定對於後面route章節的學習是非常有幫助的。
3,在link-to助手內增加額外屬性
handlebars允許你直接在link-to助手增加額外的屬性,經過模板渲染之後a標籤就有了增加的額外屬性了。
比如你可用為a標籤增加CSS的class。
handlebars允許你直接在link-to助手增加額外的屬性,經過模板渲染之後a標籤就有了增加的額外屬性了。
比如你可用為a標籤增加CSS的class。
{{link-to "show text info" 'posts.detail' 1 class="btn btn-primary"}}
{{#link-to "posts.detail" 1 class="btn btn-primary"}}show text info{{/link-to}}
上述兩種寫法都是可以的,渲染的結果也是一樣的。渲染之後的HTML為:
<a id="ember434" href="/posts/1" class="btn btn-primary ember-view">show text info</a>
注意:上述兩種方式的寫法所設定的引數的位置不能調換。但是官網沒有看到這方面的說明,有可能是我的演示例項的問題,如果讀者你的可用歡迎給我留言。
第一種方式,顯示的文字必須放在最前面,並且中間的引數是路由設定,最有一個引數是額外的屬性設定,如果你還要其他的屬性需要設定仍然只能放在最後面。
第二章方式的引數位置也是有要求的,第一個引數必須是路由設定,後面的引數設定額外的屬性。
對於渲染之後的HTML程式碼中出現標籤id為ember,或者ember-xxx,這些屬性都是Ember預設生成的,我們可以暫時不用理它。
綜合,本來這篇是講解link-to的,但是由於涉及到了route的配置就順便講講,有點難度,主要在路由的巢狀這個知識點上,但是對於後面的route這一章的學習是很有幫助的,route的設定幾乎都是為URL設定的。這兩者是緊密關聯的!