Ember 類的定義、初始化、繼承

2018-01-06 16:40 更新

Ember JS提供一套自己的類系統(tǒng),普通的JavaScript標(biāo)準(zhǔn)類不能自動(dòng)更新屬性值,Ember JS的類會(huì)自動(dòng)觸發(fā)觀察者,自動(dòng)更新屬性值、自動(dòng)刷新模板上的屬性值。如果一個(gè)類是Ember JS提供的可以看到前綴命名空間是Ember.Object。 Ember類定義使用extend()方法,創(chuàng)建類實(shí)例使用create()方法,可以在方法傳入?yún)?shù),但是參數(shù)要以hash列表方式傳入。

Ember JS重寫了標(biāo)準(zhǔn)JavaScript的數(shù)組類Array,并且為了與標(biāo)準(zhǔn)JavaScript類區(qū)別命名為Ember.EnumerableAPI介紹

Ember JS還擴(kuò)展了String屬性的特性,提供了一系列特有的處理方法,API介紹。

關(guān)于類的命名規(guī)則在此不做介紹,自己網(wǎng)上找一份Java的命名規(guī)則的教材看看即可。

開始之前先做好準(zhǔn)備工作,首先創(chuàng)建一個(gè)HTML文件,并引入Ember JS所必須的文件(后面會(huì)介紹一種更加簡單的方法去搭建EmberJS的項(xiàng)目方法,當(dāng)然如果你有時(shí)間也可以提前去了解,這種方式是使用Ember CLI搭建EmberJS的項(xiàng)目)。

  1. Ember.js ? Guides
  2. // 在這里編寫Ember代碼

上面代碼是一個(gè)簡單的HTML文件,所需的Ember庫直接使用CDN

類定義

下面定義一個(gè)Person類,定義方式如下:

  1. Person?=?Ember.Object.extend({
  2. ??say(thing)?{
  3. ????alert(name);
  4. ??}
  5. });

上面代碼定義了一個(gè)Person類,并且在類里面還定義了一個(gè)方法say,方法傳入一個(gè)參數(shù)thing。方法體僅僅是打印了傳入的參數(shù)。

類繼承

在子類重寫父類的方法,并在方法里調(diào)用_super()方法來調(diào)用父類中對(duì)應(yīng)的方法觸發(fā)父類方法的行為。

  1. Person?=?Ember.Object.extend({
  2. ????
  3. ??say(thing)?{
  4. ????var?name?=?this.get('name');
  5. ????alert(name?+?"?says:?"?+?thing);
  6. ??}
  7. });
  8. Soldier?=?Person.extend({
  9. ????
  10. ??say(thing)?{
  11. ????//?this?will?call?the?method?in?the?parent?class?(Person#say),?appending
  12. ????//?the?string?",?sir!"?to?the?variable?`thing`?passed?in
  13. ????this._super(thing?+?",?sir!");
  14. ??}
  15. });
  16. var?yehuda?=?Soldier.create({
  17. ??name:?"Yehuda?Katz"
  18. });
  19. yehuda.say("Yes");?//?alerts?"Yehuda?Katz?says:?Yes,?sir!"

運(yùn)行代碼,刷新瀏覽器,可以看到如下結(jié)果:

運(yùn)行結(jié)果截圖

結(jié)果正確了,但是我們還不知道類是怎么初始化的,它初始化的順序又是怎么樣的呢?其實(shí)每個(gè)類都有一個(gè)默認(rèn)的初始化方法,555……別急,接著往下看。

類實(shí)例化

要獲取一個(gè)類的實(shí)例只需要調(diào)用類的create()方法即可。

  1. Person = Ember.Object.extend({
  2. show() {
  3. console.log("My name is " + this.get('name'));
  4. }
  5. });
  6. var person = Person.create({
  7. name: 'ubuntuvim'
  8. });
  9. person.show(); // My name is ubuntuvim
  10. var person2 = Person.create({
  11. pwd: 'ubuntuvim'
  12. });
  13. // 由于創(chuàng)建person2的時(shí)候沒有設(shè)置name的值,默認(rèn)是undefined
  14. person2.show(); // My name is undefined

結(jié)果圖

注意:處于性能的考慮在使用create()方法創(chuàng)建實(shí)例的時(shí)候,不允許新定義、重寫計(jì)算屬性,也不推薦新定義、重寫普通方法,Ember推薦在使用create()方法時(shí)只是傳遞簡單的參數(shù),比如上述代碼的{name: 'ubuntuvim'}。如果你需要新地定義、重寫方法請(qǐng)新建一個(gè)子類來實(shí)現(xiàn)。

create()方法內(nèi)定義計(jì)算屬性,運(yùn)行后會(huì)直接報(bào)如下圖的報(bào)錯(cuò)信息。

  1. Person = Ember.Object.create({
  2. show() {
  3. console.log("My name is " + this.get('name'));
  4. },
  5. fullName: Ember.computed(function() {
  6. console.log("computed properties.");
  7. })
  8. });

報(bào)錯(cuò)信息

類初始化

前面提過,我們?cè)陬惱^承的時(shí)候到底類是怎么初始化,這節(jié)就介紹類的初始化,Ember定義了一個(gè)init()方法,此方法在類被實(shí)例化的時(shí)候自動(dòng)調(diào)用。

  1. Parent = Ember.Object.extend({
  2. init() {
  3. console.log("parent init...");
  4. },
  5. show() {
  6. console.log("My name is " + this.get('name'));
  7. },
  8. others() {
  9. console.log("the method in parent class..");
  10. }
  11. });
  12. //parent = Parent.create({
  13. // name: 'parent'
  14. //});
  15. Child = Parent.extend({
  16. init() {
  17. console.log("child init...");
  18. },
  19. show() {
  20. this._super();
  21. }
  22. });
  23. child = Child.create({
  24. name: 'child'
  25. });
  26. child.show();
  27. child.others();

注意init()方法只有在類的create()方法被調(diào)用的時(shí)候才會(huì)被自動(dòng)調(diào)用,上面的例子中,如果只是child.others()這個(gè)方法父類并不會(huì)調(diào)用init()方法,只有執(zhí)行Parent.create()這個(gè)調(diào)用的時(shí)候才會(huì)執(zhí)行init()方法。 上面代碼如果把Parent.create()這幾句代碼注釋掉得到的結(jié)果如下:

運(yùn)行結(jié)果

可見父類的init()方法沒有被調(diào)用,然后修改代碼,注釋掉child.others()這句,再把Parent.create()這幾句的注釋去掉。得到如下結(jié)果

去掉child.others()結(jié)果

可以看到父類的init()方法被調(diào)用了!由此可見init()方法是在調(diào)用create()方法的時(shí)候才調(diào)用的。 在項(xiàng)目中有可能你需要繼承Ember提供的組件,比如繼承Ember.Component類,此時(shí)你就要注意了,在你繼承Ember的組件的時(shí)候你必須顯式的調(diào)用父類方法this._super()否則你繼承得到的類無法獲取Component提供的行為或者得到無法預(yù)知的結(jié)果。

類屬性的訪問

Ember建議訪問類的屬性使用get、set方法。如果你直接使用obj.prop這種方式訪問也是可以得到類的屬性值,但是如果你不是使用訪問器操作的就會(huì)導(dǎo)致很多問題:計(jì)算屬性不能被重新計(jì)算、無法察覺對(duì)象屬性的變化、模板也不能自動(dòng)更新。

  1. Person = Ember.Object.extend({
  2. name: 'ubuntuvim'
  3. });
  4. // Ember 推薦的訪問方式
  5. var person = Person.create();
  6. console.log("My name is " + person.get('name'));
  7. person.set('name', "Tobias Funke");
  8. console.log("My name is " + person.get('name'));
  9. console.log("---------------------------");
  10. // 不推薦的方式
  11. var person2 = Person.create();
  12. console.log("My name is " + person2.name);
  13. person2.name = "Tobias Funke";
  14. console.log("My name is " + person2.name);

Ember為我們封裝了get、set實(shí)現(xiàn)細(xì)節(jié),開發(fā)者直接使用即可。
最后感謝唯獨(dú)莪靑睞的指正。
博文完整代碼放在Github(博文經(jīng)過多次修改,博文上的代碼與github代碼可能又出入,不過影響不大!),如果你覺得博文對(duì)你有點(diǎn)用在github項(xiàng)目上給我個(gè)star吧。您的肯定對(duì)我來說是最大的動(dòng)力??!

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)