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.ObjectEmber類定義使用extend()方法,創(chuàng)建類實(shí)例使用create()方法,可以在方法傳入?yún)?shù),但是參數(shù)要以hash列表方式傳入。

Ember JS重寫(xiě)了標(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ī)則的教材看看即可。

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






  

    
    Ember.js ? Guides 

  





   

    

    


//  在這里編寫(xiě)Ember代碼



  

   

   

  

  

  

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

類定義

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

Person?=?Ember.Object.extend({
??say(thing)?{
????alert(name);
??}
});

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

類繼承

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

Person?=?Ember.Object.extend({
????
??say(thing)?{
????var?name?=?this.get('name');
????alert(name?+?"?says:?"?+?thing);
??}
});


Soldier?=?Person.extend({
????
??say(thing)?{
????//?this?will?call?the?method?in?the?parent?class?(Person#say),?appending
????//?the?string?",?sir!"?to?the?variable?`thing`?passed?in
????this._super(thing?+?",?sir!");
??}
});


var?yehuda?=?Soldier.create({
??name:?"Yehuda?Katz"
});


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()方法即可。

Person = Ember.Object.extend({
    show() {
        console.log("My name is " + this.get('name'));
    }
});
var person = Person.create({
    name: 'ubuntuvim'
});
person.show();  // My name is ubuntuvim

    
var person2 = Person.create({
    pwd: 'ubuntuvim'
});
//  由于創(chuàng)建person2的時(shí)候沒(méi)有設(shè)置name的值,默認(rèn)是undefined
person2.show();  // My name is undefined

結(jié)果圖

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

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

Person = Ember.Object.create({
    show() {
        console.log("My name is " + this.get('name'));
    },
    fullName: Ember.computed(function() {
        console.log("computed properties.");
    })
});

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

類初始化

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

Parent = Ember.Object.extend({
    init() {
        console.log("parent init...");
    },
    show() {
        console.log("My name is " + this.get('name'));
    },
    others() {
        console.log("the method in parent class..");
    }
});
//parent = Parent.create({
//    name: 'parent'
//});  

    
Child = Parent.extend({
    init() {
        console.log("child init...");
    },
    show() {
        this._super();
    }
});


child = Child.create({
    name: 'child'
});    
child.show();
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é)果

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

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

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

類屬性的訪問(wèn)

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

Person = Ember.Object.extend({
    name: 'ubuntuvim'
});
// Ember 推薦的訪問(wèn)方式
var person = Person.create();
console.log("My name is " + person.get('name'));
person.set('name', "Tobias Funke");
console.log("My name is " + person.get('name'));   


console.log("---------------------------");
//  不推薦的方式
var person2 = Person.create();    
console.log("My name is " + person2.name);
person2.name = "Tobias Funke";
console.log("My name is " + person2.name);

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

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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)