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

Ember calculates the property


May 09, 2021 Ember.js Reference documents



Simple calculation of properties

Simply put, calculating a property is declaring a function as a property, similar to calling a function that Ember automatically calls. The biggest feature of computational properties is that they can automatically detect changes and update data in a timely manner.

  1. Person = Ember.Object.extend({
  2. firstName: null,
  3. lastName: null,
  4. // fullName 就是一个计算属性
  5. fullName: Ember.computed('firstName', 'lastName', function() {
  6. return this.get('firstName') + ", " + this.get('lastName');
  7. })
  8. });
  9. // 实例化同时传入参数
  10. var piter = Person.create({
  11. firstName: 'chen',
  12. lastName: 'ubuntuvim'
  13. });
  14. console.log(piter.get('fullName')); // output >> chen, ubuntuvim

Calculating properties is actually a function, and if you've jQuery、Extjs be familiar with it, as defined in both frameworks. It's Ember this function is treated as a property and the return value of the function can be obtained through get.

Calculate the property chain

In Ember a calculated property can also call another calculated property, forming a chain of calculated properties, or it can be used to extend a method. Add a description() method to the previous instance.

  1. Person = Ember.Object.extend({
  2. firstName: null,
  3. lastName: null,
  4. age: null,
  5. county: null,
  6. // fullName 就是一个计算属性
  7. fullName: Ember.computed('firstName', 'lastName', function() {
  8. return this.get('firstName') + ", " + this.get('lastName');
  9. }),
  10. description: Ember.computed('fullName', 'age', 'county', function() {
  11. return this.get('fullName') + " age " + this.get('age') + " county " + this.get('county');
  12. })
  13. });
  14. // 实例化同时传入参数
  15. var piter = Person.create({
  16. firstName: 'chen',
  17. lastName: 'ubuntuvim',
  18. age: 25,
  19. county: 'china'
  20. });
  21. console.log(piter.get('description')); // output >> chen, ubuntuvim

When the user uses set method to change the value firstName and then get('description') value is also the updated value.

Rewrite the get, set method of calculating properties

Note to pass the override property into the computed to distinguish between the definition computed the computed function the last argument at the time of hash

  1. // 重写计算属性的get、set方法
  2. Person = Ember.Object.extend({
  3. firstName: null,
  4. lastName: null,
  5. // 重写计算属性fullName的get、set方法
  6. fullName: Ember.computed('firstName', 'lastName', {
  7. get(key) {
  8. return this.get('firstName') + "," + this.get('lastName');
  9. },
  10. set(key, value) {
  11. // 这个官方文档使用的代码,但是我运行的时候出现 Uncaught SyntaxError: Unexpected token [ 这个错误,不知道是否是缺少某个文件,后续会补上;
  12. // console.log("value = " + value);
  13. // var [ firstName, lastName ] = value.split(/\s+/);
  14. var firstName = value.split(/\s+/)[0];
  15. var lastName = value.split(/\s+/)[1];
  16. this.set('firstName', firstName);
  17. this.set('lastName', lastName);
  18. }
  19. }),
  20. // 对于普通的属性无法重写get、set方法
  21. // firstName: Ember.computed('firstName', {
  22. // get(key) {
  23. // return this.get('firstName') + "@@";
  24. // },
  25. // set(key, value) {
  26. // this.set('firstName', value);
  27. // }
  28. // })
  29. });
  30. var jack = Person.create();
  31. jack.set('fullName', "james kobe");
  32. console.log(jack.get('firstName'));
  33. console.log(jack.get('lastName'));

Ember calculates the property

The statistic that calculates the property value

We often encounter a situation where a calculated property value depends on an array or other object, such as this piece of code in todos example. Ember

  1. export default Ember.Controller.extend({
  2. todos: [
  3. Ember.Object.create({ isDone: true }),
  4. Ember.Object.create({ isDone: false }),
  5. Ember.Object.create({ isDone: true })
  6. ],
  7. remaining: Ember.computed('[email protected]', function() {
  8. var todos = this.get('todos');
  9. return todos.filterBy('isDone', false).get('length');
  10. })
  11. });

The value of remaining property remaining is dependent on the todos H ere's another knowledge point: there's a key like [email protected] in the code computed() method above that contains @each see a more special key [] I t is important to note that this key cannot be nested and is a property that can only get one level. For [email protected] (get multi-level properties, here's to get foo before getting name or [email protected][email protected] (nesting) are not allowed.

Ember automatically updates the calculated property values of the binding in four cases: when the isDone property value of any object in the todos array changes; 2. when todos array; 3. when todos array; and 4. todos another array;

For example, the results of the following code demonstration;

  1. Task = Ember.Object.extend({
  2. isDone: false // 默认为false
  3. });
  4. WorkerLists = Ember.Object.extend({
  5. // 定义一个Task对象数组
  6. lists: [
  7. Task.create({ isDone: false }),
  8. Task.create({ isDone: true }),
  9. Task.create(),
  10. Task.create({ isDone: true }),
  11. Task.create({ isDone: true }),
  12. Task.create({ isDone: true }),
  13. Task.create({ isDone: false }),
  14. Task.create({ isDone: true })
  15. ],
  16. remaining: Ember.computed('[email protected]', function() {
  17. var lists = this.get('lists');
  18. // 先查询属性isDone值为false的对象,再返回其数量
  19. return lists.filterBy('isDone', false).get('length');
  20. })
  21. });
  22. // 如下代码使用到的API请查看:http://emberjs.com/api/classes/Ember.MutableArray.html
  23. var wl = WorkerLists.create();
  24. // 所有isDone属性值未做任何修改
  25. console.log('1,>> Not complete lenght is ' + wl.get('remaining')); // output 3
  26. var lists = wl.get('lists'); // 得到对象内的数组
  27. // ----- 演示第一种情况: 1. 在todos数组中任意一个对象的isDone属性值发生变化的时候;
  28. // 修改数组一个元素的isDone的 值
  29. var item1 = lists.objectAt(3); // 得到第4个元素 objectAt()方法是Ember为我们提供的
  30. // console.log('item1 = ' + item1);
  31. item1.set('isDone', false);
  32. console.log('2,>> Not complete lenght is ' + wl.get('remaining')); // output 4
  33. // --------- 2. 往todos数组新增元素的时候;
  34. lists.pushObject(Task.create({ isDone: false })); //新增一个isDone为false的对象
  35. console.log('3,>> Not complete lenght is ' + wl.get('remaining')); // output 5
  36. // --------- 3. 从todos数组删除元素的时候;
  37. lists.removeObject(item1); // 删除了一个元素
  38. console.log('4,>> Not complete lenght is ' + wl.get('remaining')); // output 4
  39. // --------- 4. 在控制器中todos数组被改变为其他的数组的时候;
  40. // 创建一个Controller
  41. TodosController = Ember.Controller.extend({
  42. // 在控制器内定义另外一个Task对象数组
  43. todosInController: [
  44. Task.create({ isDone: false }),
  45. Task.create({ isDone: true })
  46. ],
  47. // 使用键”@each.isDone“遍历得到的filterBy()方法过滤后的对象的isDone属性
  48. remaining: function() {
  49. // remaining()方法返回的是控制器内的数组
  50. return this.get('todosInController').filterBy('isDone', false).get('length');
  51. }.property('@each.isDone') // 指定遍历的属性
  52. });
  53. todosController = TodosController.create();
  54. var count = todosController.get('remaining');
  55. console.log('5,>> Not complete lenght is ' + count); // output 1

Ember calculates the property

In the above case, our focus on array objects is on the properties of the object, but in practice there are often many cases where we do not care whether the properties within the object have changed, but rather treat the array elements as a whole object (such as changes in the number of array elements). T he code below the code above detects changes in the elements of the array object, not changes in the isDone of the object. I n this case you can look at the following example, in which you can [] @each The difference can also be seen from the change of keys.

  1. Task = Ember.Object.extend({
  2. isDone: false, // 默认为false
  3. name: 'taskName',
  4. // 为了显示结果方便,重写toString()方法
  5. toString: function() {
  6. return '[name = '+this.get('name')+', isDone = '+this.get('isDone')+']';
  7. }
  8. });
  9. WorkerLists = Ember.Object.extend({
  10. // 定义一个Task对象数组
  11. lists: [
  12. Task.create({ isDone: false, name: 'ibeginner.sinaapp.com' }),
  13. Task.create({ isDone: true, name: 'i2cao.xyz' }),
  14. Task.create(),
  15. Task.create({ isDone: true, name: 'ubuntuvim' }),
  16. Task.create({ isDone: true , name: '[email protected]'}),
  17. Task.create({ isDone: true })
  18. ],
  19. index: null,
  20. indexOfSelectedTodo: Ember.computed('index', 'lists.[]', function() {
  21. return this.get('lists').objectAt(this.get('index'));
  22. })
  23. });
  24. var wl = WorkerLists.create();
  25. // 所有isDone属性值未做任何修改
  26. var index = 1;
  27. wl.set('index', index);
  28. console.log('Get '+wl.get('indexOfSelectedTodo').toString()+' by index ' + index);

Ember calculates the property

Ember.computed many ways to implement this component [] keys. T his is especially appropriate when you want to create an array of calculated properties. You can Ember.computed.map to build your computational properties.

  1. const Hamster = Ember.Object.extend({
  2. chores: null,
  3. excitingChores: Ember.computed('chores.[]', function() { //告诉Ember chores是一个数组
  4. return this.get('chores').map(function(chore, index) {
  5. //return `${index} --> ${chore.toUpperCase()}`; // 可以使用${}表达式,并且在表达式内可以直接调用js方法
  6. return `${chore}`; //返回元素值
  7. });
  8. })
  9. });
  10. // 为数组赋值
  11. const hamster = Hamster.create({
  12. // 名字chores要与类Hamster定义指定数组的名字一致
  13. chores: ['First Value', 'write more unit tests']
  14. });
  15. console.log(hamster.get('excitingChores'));
  16. hamster.get('chores').pushObject("Add item test"); //add an item to chores array
  17. console.log(hamster.get('excitingChores'));

Ember provides another way to define the calculated properties of array types.

  1. const Hamster = Ember.Object.extend({
  2. chores: null,
  3. excitingChores: Ember.computed('chores.[]', function() {
  4. return this.get('chores').map(function(chore, index) {
  5. //return `${index} --> ${chore.toUpperCase()}`; // 可以使用${}表达式,并且在表达式内可以直接调用js方法
  6. return `${chore}`; //返回元素值
  7. });
  8. })
  9. });
  10. // 为数组赋值
  11. const hamster = Hamster.create({
  12. // 名字chores要与类Hamster定义指定数组的名字一致
  13. chores: ['First Value', 'write more unit tests']
  14. });
  15. console.log(hamster.get('excitingChores'));
  16. hamster.get('chores').pushObject("Add item test"); //add an item to chores array
  17. console.log(hamster.get('excitingChores'));

lt; T he full code of the blog post is placed in Github (the blog post has been modified several times, and the code on the blog 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!!