课程表

Ember.js 基础

Ember.js 对象模型

Ember.js handlebars模板

Ember.js 路由

Ember.js 组件

Ember.js 控制器

Ember.js 模型

Ember.js 测试

工具箱
速查手册

Ember 观察者

当前位置:免费教程 » JS/JS库/框架 » Ember.js

Ember可以检测任何属性的变化,包括计算属性。

观察者使用

Ember可以察觉所有属性的变化,包括计算属性。观察者是非常有用的,特别是计算属性绑定之后需要同步的时候。 观察者经常被Ember开发过度使用。Ember框架本身已经大量使用观察者,但是对于大多数的开发者面对开发问题时使用计算属性是更适合的解决方案。 使用方式:可以用Ember.observer创建一个对象为观察者。

  1. // Observer对于Emberjs来说非常重要,前面你看到的很多代码都是与它有关系,计算属性之所以能更新也是因为它
  2. Person = Ember.Object.extend({
  3. firstName: null,
  4. lastName: null,
  5.  
  6. fullName: Ember.computed('firstName', 'lastName', function() {
  7. return this.get('firstName') + " " + this.get('lastName');
  8. }),
  9.  
  10. // 当fullName被改变的时候触发观察者
  11. fullNameChange: Ember.observer('fullName', function() {
  12. console.log("The fullName is changed by caller");
  13. //return this.get('fullName');
  14. })
  15. });
  16.  
  17. var person = Person.create({
  18. firstName: 'chen',
  19. lastName: 'ubuntuvim'
  20. });
  21. // 如果被观察的计算属性还没执行过get()方法不会触发观察者
  22. console.log('fullName = ' + person.get('fullName'));
  23. // fullName是依赖firstName和lastName的,这里改变了firstName的值,计算属性会自动更新,
  24. // fullName被改变了所以会触发观察者
  25. person.set('firstName', 'change firstName value'); // 观察者会被触发
  26. console.log('fullName = ' + person.get('fullName'));

fullName是依赖firstNamelastName的,调用set()方法改变了firstName的值,自然的导致fullName的值也被改变了,fullName变化了就触发观察者。从执行的结果就可以看出来;

运行结果图

Ember还为开发者提供了另一种使用观察者的方式。这种方式使你可以在类定义之外为某个计算属性增加一个观察者。

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

观察者与异步

目前,观察者在Ember中是同步的(不是笔误,官网就是这么说的Observers in Ember are currently synchronous.)。这就意味着只要计算属性一发生变化就会触发观察者。也因为这个原因很容易就会引入这样的bug在计算属性没有同步的时候。比如下面的代码;

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

然而由于同步的原因如果你的的观察者同时观察多个属性,就会导致观察者执行多次。

  1. person = Ember.Object.extend({
  2. firstName: null,
  3. lastName: null,
  4.  
  5. fullName: Ember.computed('firstName', 'lastName', function() {
  6. return this.get('firstName') + " " + this.get('lastName');
  7. }),
  8.  
  9. // 当fullName被改变的时候触发观察者
  10. fullNameChange: Ember.observer('fullName', function() {
  11. console.log("The fullName is changed by caller");
  12. //return this.get('fullName');
  13. })
  14. });
  15. Person.reopen({
  16. partOfNameChanged: Ember.observer('firstName', 'lastName', function() {
  17. // 同时观察了firstName和lastName两个属性
  18. console.log('========partOfNameChanged======');
  19. })
  20. });
  21. var person = Person.create({
  22. firstName: 'chen',
  23. lastName: 'ubuntuvim'
  24. });
  25.  
  26. person.set('firstName', '[firstName]');
  27. person.set('lastName', '[lastName]');

run result

显然上述代码执行了两次set()所以观察者也会执行2次,但是如果开发中需要设置只能执行一次观察出呢?Ember提供了一个once()方法,这个方法会在下一次循环所有绑定属性都同步的时候执行。

  1. Person = Ember.Object.extend({
  2. firstName: null,
  3. lastName: null,
  4.  
  5. fullName: Ember.computed('firstName', 'lastName', function() {
  6. return this.get('firstName') + " " + this.get('lastName');
  7. }),
  8.  
  9. // 当fullName被改变的时候触发观察者
  10. fullNameChange: Ember.observer('fullName', function() {
  11. console.log("The fullName is changed by caller");
  12. //return this.get('fullName');
  13. })
  14. });
  15. Person.reopen({
  16. partOfNameChanged: Ember.observer('firstName', 'lastName', function() {
  17. // 同时观察了firstName和lastName两个属性
  18. // 方法partOfNameChanged本身还是会执行多次,但是方法processFullName只会执行一次
  19. console.log('========partOfNameChanged======'); //
  20. Ember.run.once(this, 'processFullName');
  21. }),
  22. processFullName: Ember.observer('fullName', function() {
  23. // 当你同时设置多个属性的时候,此观察者只会执行一次,并且是发生在下一次所有属性都被同步的时候
  24. console.log('fullName = ' + this.get('fullName'));
  25. })
  26. });
  27.  
  28. var person = Person.create({
  29. firstName: 'chen',
  30. lastName: 'ubuntuvim'
  31. });
  32.  
  33. person.set('firstName', '[firstName]');
  34. person.set('lastName', '[lastName]');

run result

观察者与对象初始化

观察者一直到对象初始化完成之后才会执行。 如果你想观察者在对象初始化的时候就执行你必须要手动调用Ember.on()方法。这个方法会在对象初始化之后就执行。

  1. Person = Ember.Object.extend({
  2. salutation:null,
  3. init() {
  4. this.set('salutation', 'hello');
  5. console.log('init....');
  6. },
  7. salutationDidChange: Ember.on('init', Ember.observer('salutation', function() {
  8. console.log('salutationDidChange......');
  9. }))
  10. });
  11.  
  12. var p = Person.create();
  13. p.get('salutationDidChange'); // output > init.... salutationDidChange......
  14. console.log(p.get('salutation')); // output > hello
  15. p.set('salutation'); // output > salutationDidChange......

未获取过值的计算属性不会触发观察者

如果一个计算属性从来没有调用过get()方法获取的其值,观察者就不会被触发,即使是计算属性的值发生变化了。你可以这么认为,观察者是根据调用get()方法前后的值比较判断出计算属性值是否发生改变了。如果没调用过get()之前的改变观察者认为是没有变化。 通常我们不需要担心这个问题会影响到程序代码,因为几乎所有被观察的计算属性在触发前都会执行取值操作。如果你仍然担心观察者不会被触发,你可以在init()方法了执行一次get操作。这样足以保证你的观察在触发之前是执行过get操作的。

对于初学者来说,属性值的自动更新还是有点难以理解,到底它是怎么个更新法!!!先别急,先放一放,随着不断深入学习你就会了解到这个是多么强大的特性。

转载本站内容时,请务必注明来自W3xue,违者必究。
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号