Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Ember Observer


May 09, 2021 Ember.js Reference documents



Ember detect changes in any property, including calculated properties.

Used by the observer

Ember aware of changes in all attributes, including calculated properties. O bservers are useful, especially if synchronization is required after calculating property bindings. O bservers are often overused by Ember. Ember framework itself is already heavily used by observers, but it is a more appropriate solution for most developers to use compute attributes in the face of development problems. How to use: Ember.observer to create an object as an observer.

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

fullName firstName lastName and the set() firstName which naturally causes fullName to change, fullName to trigger the observer. As can be seen from the results of implementation;

Ember Observer

Ember provides developers with another way to use observers. This way you can add an observer to a calculated property outside of the class definition.

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

Observers and asynchronous

Currently, observers Ember in Ember (either by mistake, as the official website says by Observers in Ember are currently synchronous. 。 T his means that as soon as the calculated property changes, the observer is triggered. I t is also easy to introduce such bugs when bug are not synchronized. For example, the following code;

  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. });

However, for synchronization reasons, if your observer observes multiple properties at the same time, it causes the observer to perform multiple times.

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

Ember Observer

Obviously the above code executes set() so the observer will also execute twice, but what if you need to set up in development to perform only one observation? Ember provides a once() method that executes the next time all the binding properties in the loop are synchronized.

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

Ember Observer

The observer initializes with the object

The observer does not execute until the object initialization is complete. I f you want the observer to execute when the object is initialized, you must manually Ember.on() method. This method is executed after the object is initialized.

  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. var p = Person.create();
  12. p.get('salutationDidChange'); // output > init.... salutationDidChange......
  13. console.log(p.get('salutation')); // output > hello
  14. p.set('salutation'); // output > salutationDidChange......

Calculated properties that do not get over-values do not trigger observers

If a calculated property never calls its get() the observer is not triggered, even if the value of the calculated property changes. Y ou can argue that the observer determines whether the get() has changed based on a comparison of values before and after calling the get() method. I f you haven't get() change observer thinks there is no change. U sually we don't have to worry about this affecting the program code, because almost all of the observed compute properties perform value-taking operations before they are triggered. I f you're still worried that the observer won't be init() a get operation in the get method. T his is sufficient to ensure that your observations were geodesy before they were triggered.
For beginners, the automatic update of property values is still a bit difficult to understand, in the end how it is an update method!!! D on't worry, let's put it first, and as you learn more, you'll learn how powerful this is.
The full code of the blog post is placed in Github (the blog post has been modified several times, and the code on the blog post may be different from the github code, but the impact is small!). I f you think the blog post is a bit of a github project for you, give me star Yours is definitely the biggest motivation for me!!