国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

Ember 觀察者

2018-12-11 14:46 更新

Ember可以檢測(cè)任何屬性的變化,包括計(jì)算屬性。

觀察者使用

Ember可以察覺所有屬性的變化,包括計(jì)算屬性。觀察者是非常有用的,特別是計(jì)算屬性綁定之后需要同步的時(shí)候。 觀察者經(jīng)常被Ember開發(fā)過度使用。Ember框架本身已經(jīng)大量使用觀察者,但是對(duì)于大多數(shù)的開發(fā)者面對(duì)開發(fā)問題時(shí)使用計(jì)算屬性是更適合的解決方案。 使用方式:可以用Ember.observer創(chuàng)建一個(gè)對(duì)象為觀察者。

// Observer對(duì)于Emberjs來說非常重要,前面你看到的很多代碼都是與它有關(guān)系,計(jì)算屬性之所以能更新也是因?yàn)樗?Person = Ember.Object.extend({
  firstName: null,
  lastName: null,


  fullName: Ember.computed('firstName', 'lastName', function() {
    return this.get('firstName') + " " + this.get('lastName');
  }),


  //  當(dāng)fullName被改變的時(shí)候觸發(fā)觀察者
  fullNameChange: Ember.observer('fullName', function() {
    console.log("The fullName is changed by caller");
    //return this.get('fullName');
  })
});


var person = Person.create({
  firstName: 'chen',
  lastName: 'ubuntuvim'
});
// 如果被觀察的計(jì)算屬性還沒執(zhí)行過get()方法不會(huì)觸發(fā)觀察者
console.log('fullName = ' + person.get('fullName'));  
//  fullName是依賴firstName和lastName的,這里改變了firstName的值,計(jì)算屬性會(huì)自動(dòng)更新,
//  fullName被改變了所以會(huì)觸發(fā)觀察者
person.set('firstName', 'change firstName value');  // 觀察者會(huì)被觸發(fā)
console.log('fullName = ' + person.get('fullName'));

fullName是依賴firstNamelastName的,調(diào)用set()方法改變了firstName的值,自然的導(dǎo)致fullName的值也被改變了,fullName變化了就觸發(fā)觀察者。從執(zhí)行的結(jié)果就可以看出來;

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

Ember還為開發(fā)者提供了另一種使用觀察者的方式。這種方式使你可以在類定義之外為某個(gè)計(jì)算屬性增加一個(gè)觀察者。

person.addObserver('fullName', function() {
    // deal with the change…
});

觀察者與異步

目前,觀察者在Ember中是同步的(不是筆誤,官網(wǎng)就是這么說的Observers in Ember are currently synchronous.)。這就意味著只要計(jì)算屬性一發(fā)生變化就會(huì)觸發(fā)觀察者。也因?yàn)檫@個(gè)原因很容易就會(huì)引入這樣的bug在計(jì)算屬性沒有同步的時(shí)候。比如下面的代碼;

Person.reopen({
  lastNameChanged: Ember.observer('lastName', function() {
    // The observer depends on lastName and so does fullName. Because observers
    // are synchronous, when this function is called the value of fullName is
    // not updated yet so this will log the old value of fullName
    console.log(this.get('fullName'));
  })
});

然而由于同步的原因如果你的的觀察者同時(shí)觀察多個(gè)屬性,就會(huì)導(dǎo)致觀察者執(zhí)行多次。

person = Ember.Object.extend({
  firstName: null,
  lastName: null,


  fullName: Ember.computed('firstName', 'lastName', function() {
    return this.get('firstName') + " " + this.get('lastName');
  }),


  //  當(dāng)fullName被改變的時(shí)候觸發(fā)觀察者
  fullNameChange: Ember.observer('fullName', function() {
    console.log("The fullName is changed by caller");
    //return this.get('fullName');
  })
});
Person.reopen({
  partOfNameChanged: Ember.observer('firstName', 'lastName', function() {
    //  同時(shí)觀察了firstName和lastName兩個(gè)屬性
    console.log('========partOfNameChanged======');
  })
});
var person = Person.create({
  firstName: 'chen',
  lastName: 'ubuntuvim'
});


person.set('firstName', '[firstName]');
person.set('lastName', '[lastName]');

run result

顯然上述代碼執(zhí)行了兩次set()所以觀察者也會(huì)執(zhí)行2次,但是如果開發(fā)中需要設(shè)置只能執(zhí)行一次觀察出呢?Ember提供了一個(gè)once()方法,這個(gè)方法會(huì)在下一次循環(huán)所有綁定屬性都同步的時(shí)候執(zhí)行。

Person = Ember.Object.extend({
  firstName: null,
  lastName: null,


  fullName: Ember.computed('firstName', 'lastName', function() {
    return this.get('firstName') + " " + this.get('lastName');
  }),


  //  當(dāng)fullName被改變的時(shí)候觸發(fā)觀察者
  fullNameChange: Ember.observer('fullName', function() {
    console.log("The fullName is changed by caller");
    //return this.get('fullName');
  })
});
Person.reopen({
  partOfNameChanged: Ember.observer('firstName', 'lastName', function() {
    //  同時(shí)觀察了firstName和lastName兩個(gè)屬性
    //  方法partOfNameChanged本身還是會(huì)執(zhí)行多次,但是方法processFullName只會(huì)執(zhí)行一次
    console.log('========partOfNameChanged======');  //  
    Ember.run.once(this, 'processFullName');
  }),
  processFullName: Ember.observer('fullName', function() {
    // 當(dāng)你同時(shí)設(shè)置多個(gè)屬性的時(shí)候,此觀察者只會(huì)執(zhí)行一次,并且是發(fā)生在下一次所有屬性都被同步的時(shí)候
    console.log('fullName = ' + this.get('fullName'));
  })
});


var person = Person.create({
  firstName: 'chen',
  lastName: 'ubuntuvim'
});


person.set('firstName', '[firstName]');
person.set('lastName', '[lastName]');

run result

觀察者與對(duì)象初始化

觀察者一直到對(duì)象初始化完成之后才會(huì)執(zhí)行。 如果你想觀察者在對(duì)象初始化的時(shí)候就執(zhí)行你必須要手動(dòng)調(diào)用Ember.on()方法。這個(gè)方法會(huì)在對(duì)象初始化之后就執(zhí)行。

Person = Ember.Object.extend({
  salutation:null,
  init() {
    this.set('salutation', 'hello');
    console.log('init....');
  },
  salutationDidChange: Ember.on('init', Ember.observer('salutation', function() {
    console.log('salutationDidChange......');
  }))
});


var p = Person.create();
p.get('salutationDidChange');  //  output > init....  salutationDidChange......
console.log(p.get('salutation'));  // output > hello
p.set('salutation');  //  output > salutationDidChange......

未獲取過值的計(jì)算屬性不會(huì)觸發(fā)觀察者

如果一個(gè)計(jì)算屬性從來沒有調(diào)用過get()方法獲取的其值,觀察者就不會(huì)被觸發(fā),即使是計(jì)算屬性的值發(fā)生變化了。你可以這么認(rèn)為,觀察者是根據(jù)調(diào)用get()方法前后的值比較判斷出計(jì)算屬性值是否發(fā)生改變了。如果沒調(diào)用過get()之前的改變觀察者認(rèn)為是沒有變化。 通常我們不需要擔(dān)心這個(gè)問題會(huì)影響到程序代碼,因?yàn)閹缀跛斜挥^察的計(jì)算屬性在觸發(fā)前都會(huì)執(zhí)行取值操作。如果你仍然擔(dān)心觀察者不會(huì)被觸發(fā),你可以在init()方法了執(zhí)行一次get操作。這樣足以保證你的觀察在觸發(fā)之前是執(zhí)行過get操作的。
對(duì)于初學(xué)者來說,屬性值的自動(dòng)更新還是有點(diǎn)難以理解,到底它是怎么個(gè)更新法!?。∠葎e急,先放一放,隨著不斷深入學(xué)習(xí)你就會(huì)了解到這個(gè)是多么強(qiáng)大的特性。
博文完整代碼放在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)