不得不說(shuō),Ember的更新是在是太快了??!本教程還沒(méi)寫(xiě)到一半就又更新到v2.1.0
了?。。。〔贿^(guò)為了統(tǒng)一還是使用官方v2.0.0
的參考文檔??!
從本篇開(kāi)始進(jìn)入新的一章——組件。這一章將用6篇文章介紹Ember的組件,從它的定義開(kāi)始知道它的使用方式,我將為你一一解答!
準(zhǔn)備工作: 本章代碼統(tǒng)一訪(fǎng)問(wèn)項(xiàng)目chapter4_components下,項(xiàng)目代碼可以在以下網(wǎng)址上找到: https://github.com/ubuntuvim/my_emberjs_code
與之前的文章一樣,項(xiàng)目仍然是使用Ember CLI命令創(chuàng)建項(xiàng)目和各個(gè)組件文件。
創(chuàng)建項(xiàng)目并測(cè)試運(yùn)行,首先執(zhí)行如下四條命令,最后在瀏覽器執(zhí)行:http://localhost:4200/。
ember new chapter4_components
cd chapter4_components
ember server
如果你能在頁(yè)面上看到Welcome to Ember說(shuō)明項(xiàng)目框架搭建成功!那么你可以繼續(xù)往下看了,否則想搭建好項(xiàng)目再往下學(xué)習(xí)~~~
創(chuàng)建組件方法很簡(jiǎn)單:ember generate component my-component-name
。一條命令即可,但是需要注意的是組件的名稱(chēng)必須要包含中劃線(xiàn)-
,比如blog-post
、test-component
、audio-player-controls
這種格式的命名是合法,但是post
、test
這種方式的命名是不合法的!其一是為了防止用戶(hù)自定義的組件名與W3C規(guī)定的元素標(biāo)簽名重復(fù);其二是為了確保Ember能自動(dòng)檢測(cè)到用戶(hù)自定義的組件。
下面定義一個(gè)組件,ember g component blog-post
。Ember CLI會(huì)自動(dòng)為你創(chuàng)建組件對(duì)應(yīng)的的模板,執(zhí)行這條命令之后你可以在app/components
和app/templates/components
下看到創(chuàng)建的文件。
<h2>{{title}}</h2>
<p>{{yield}}</p>
<p>Edit title: {{input type="text" value=title}}</p>
為了演示組件的使用需要做些準(zhǔn)備工作:
ember g route index
// app/routes/index.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return [
{ id: 1, title: 'Bower: dependencies and resolutions new', body: "In the bower.json file, I see 2 keys dependencies and resolutionsWhy is that so? I understand Bower has a flat dependency structure. So has it got anything to do with that ?", category: 'java' },
{ id: 2, title: 'Highly Nested JSON Payload - hasMany error', body: "Welcome to the Ember.js discussion forum. We're running on the open source, Ember.js-powered Discourse forum software. They are also providing the hosting for us. Thanks guys! Please use this space for discussion abo… read more", category: 'php' },
{ id: 3, title: 'Passing a jwt to my REST adapter new ', body: "This sets up a binding between the category query param in the URL, and the category property on controller:articles. In other words, once the articles route has been entered, any changes to the category query param in the URL will update the category property on controller:articles, and vice versa.", category: 'java'}
];
}
});
{{#each model as |item|}}
{{#blog-post title=item.title}}
{{item.body}}
{{/blog-post}}
{{/each}}
在這段代碼中,使用了自定義的組件來(lái)顯示數(shù)據(jù)。最后頁(yè)面顯示如下:
自定義的組件被渲染到了模板index.hbs
使用blog-post
的地方。并且自定義組件的HTML標(biāo)簽沒(méi)有變化。
到這里大概應(yīng)該知道怎么去使用組件了,至于它是怎么就渲染到了使用組件的地方,以及它是怎么渲染上去的。別急~~后面的文章會(huì)為你一一解答。
說(shuō)明:默認(rèn)情況下,自定義的組件會(huì)被渲染到div
標(biāo)簽內(nèi),當(dāng)然這種默認(rèn)情況也是可以修改的,比較簡(jiǎn)單在此不過(guò)多介紹,請(qǐng)自行學(xué)習(xí),網(wǎng)址:customizing-a-components-element。
用戶(hù)自定義的組件類(lèi)都需要繼承Ember.Component
類(lèi)。
通常情況下我們會(huì)把經(jīng)常使用的模板片段封裝成組件,只需要定義一次就可以在項(xiàng)目任何一個(gè)模板中使用,而且不需要編寫(xiě)任何的javascript代碼。比如上述第一點(diǎn)“自定義組件及使用”中描述的一樣。
但是如果你想你的組件有特殊的行為,并且這些行為是默認(rèn)組件類(lèi)無(wú)法提供的(比如:改變包裹組件的標(biāo)簽、響應(yīng)組件模板初始化某個(gè)狀態(tài)等),那么此時(shí)你可以自定義組件類(lèi),但是要繼承Ember.Component
,如果你自定義的組件類(lèi)沒(méi)有繼承這個(gè)類(lèi),你自定義的組件就很有可能會(huì)出現(xiàn)一些不可預(yù)知的問(wèn)題。
Ember所能識(shí)別的自定義組件類(lèi)的名稱(chēng)是有規(guī)范的。比如,你定義了一個(gè)名為blog-post
的組件,那么你的組件類(lèi)的名稱(chēng)應(yīng)該是app/components/blog-post.js
。如果組件名為audio-player-controls
那么對(duì)應(yīng)的組件類(lèi)名為app/components/audio-player-controls.js
。即:組件類(lèi)名與組件同名,這個(gè)是v2.0
的命名方法,請(qǐng)區(qū)別就版本的Ember,舊版本的組件命名規(guī)則是駝峰式的命名規(guī)則。
舉個(gè)簡(jiǎn)單的例子,在第一點(diǎn)“自定義組件及使用”中講過(guò),組件默認(rèn)會(huì)被渲染到div
標(biāo)簽內(nèi),你可以在組件類(lèi)中修改這個(gè)默認(rèn)標(biāo)簽。
// app/components/blog-post.js
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'nav'
});
這段代碼修改了包裹組件的標(biāo)簽名,頁(yè)面刷新后HTML代碼如下:
可以看到組件的HTML代碼被包含在nav
標(biāo)簽內(nèi)。
組件的動(dòng)態(tài)渲染與Java的多態(tài)有點(diǎn)相似。{{component}}
助手會(huì)延遲到運(yùn)行時(shí)才決定使用那個(gè)組件渲染頁(yè)面。當(dāng)程序需要根據(jù)數(shù)據(jù)不同渲染不同組件的時(shí),這種動(dòng)態(tài)渲染就顯得特別有用??梢允鼓愕倪壿嫼驮噲D分離開(kāi)。
那么要怎么使用呢?非常簡(jiǎn)單,只需要把組件名作為參數(shù)傳遞過(guò)去即可,比如:使用{{component 'blog-post'}}
與{{blog-post}}
結(jié)果是一致的。我們可以修改第一點(diǎn)“自定義組件及使用”實(shí)例中模板index.hbs
的代碼。
{{#each model as |item|}}
{{component 'blog-post' title=item.title}}
{{item.body}}
{{/each}}
頁(yè)面刷新之后,可以看到結(jié)果是一樣的。
下面為讀者演示如何根據(jù)數(shù)據(jù)不同渲染不同的組件。
按照慣例,先做好準(zhǔn)備工作,使用Ember CLI命令創(chuàng)建2個(gè)不同的組件。
ember g component foo-component
ember g component bar-component
<h2>Hello from bar</h2>
<p>{{post.body}}</p>
為何能用post
獲取數(shù)據(jù),因?yàn)樵谑褂媒M件的地方傳遞了參數(shù)。在模板index.hbs
中可以看到。
<h2>Hello from foo</h2>
<p>{{post.body}}</p>
修改顯示的數(shù)據(jù),注意數(shù)據(jù)的最后增加一個(gè)屬性pn
,pn
的值就是組件的名稱(chēng)。
// app/routes/index.js
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return [
{ id: 1, title: 'Bower: dependencies and resolutions new', body: "In the bower.json file, I see 2 keys dependencies and resolutionsWhy is that so? I understand Bower has a flat dependency structure. So has it got anything to do with that ?", pn: 'bar-component' },
{ id: 2, title: 'Highly Nested JSON Payload - hasMany error', body: "Welcome to the Ember.js discussion forum. We're running on the open source, Ember.js-powered Discourse forum software. They are also providing the hosting for us. Thanks guys! Please use this space for discussion abo… read more", pn: 'foo-component' },
{ id: 3, title: 'Passing a jwt to my REST adapter new ', body: "This sets up a binding between the category query param in the URL, and the category property on controller:articles. In other words, once the articles route has been entered, any changes to the category query param in the URL will update the category property on controller:articles, and vice versa.", pn: 'bar-component'}
];
}
});
修改調(diào)用組件的模板index.hbs
。
{{#each model as |item|}}
{{component item.pn post=item}}
{{/each}}
模板編譯之后會(huì)得到形如{{component foo-component post}}
的組件調(diào)用代碼。
相信你應(yīng)該了解了動(dòng)態(tài)渲染組件是怎么回事了!自己動(dòng)手試試吧~~
到此組件的定義與使用介紹完畢了,不知道你有沒(méi)有學(xué)會(huì)呢?如果你有疑問(wèn)請(qǐng)給我留言或者直接看官方教程學(xué)習(xí)。
博文完整代碼放在Github(博文經(jīng)過(guò)多次修改,博文上的代碼與github代碼可能有出入,不過(guò)影響不大?。绻阌X(jué)得博文對(duì)你有點(diǎn)用,請(qǐng)?jiān)趃ithub項(xiàng)目上給我點(diǎn)個(gè)star
吧。您的肯定對(duì)
我來(lái)說(shuō)是最大的動(dòng)力??!
更多建議: