课程表

Ember.js 基础

Ember.js 对象模型

Ember.js handlebars模板

Ember.js 路由

Ember.js 组件

Ember.js 控制器

Ember.js 模型

Ember.js 测试

工具箱
速查手册

Ember 计算属性

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

简单的计算属性

简单地来说,计算属性就是将函数声明为属性,就类似于调用了一个函数,Ember会自动调用这个函数。计算属性最大的特点就是能自动检测变化,及时更新数据。

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

计算属性其实就是一个函数,如果你接触过就jQuery、Extjs相信你回非常熟悉,在这两个框架中函数就是这么定义的。只不过在Ember中,把这种函数当做属性来处理,并且可以通过get获取函数的返回值。

计算属性链

Ember程序中,计算属性还能调用另外一个计算属性,形成计算属性链,也可以用于扩展某个方法。在上一实例的基础上增加一个description()方法。

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

当用户使用set方法改变firstName的值,然后再调用get('description')得到的值也是更新后的值。

重写计算属性的get、set方法

注意要把重写的属性作为参数传入computed方法,要区别计算属性的定义方法,定义的时候computed方法的最后一个参数是一个function,而重写的时候最后一个参数是一个hash

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

运行结果

计算属性值的统计

我们经常会遇到这种情况:某个计算属性值是依赖某个数组或者其他对象的,比如在Embertodos这个例子中有这样的一段代码。

  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('todos.@each.isDone', function() {
  8. var todos = this.get('todos');
  9. return todos.filterBy('isDone', false).get('length');
  10. })
  11. });

计算属性remaining的值于依赖数组todos。在这里还有个知识点:在上述代码computed()方法里有一个todos.@each.isDone这样的键,里面包含了一个特别的键@each(后面还会看到更特别的键[])。需要注意的是这种键不能嵌套并且是只能获取一个层次的属性。比如todos.@each.foo.name(获取多层次属性,这里是先得到foo再获取name)或者todos.@each.owner.@each.name(嵌套)这两种方式都是不允许的。

在如下4种情况Ember会自动更新绑定的计算属性值:
1.在todos数组中任意一个对象的isDone属性值发生变化的时候;
2.往todos数组新增元素的时候;
3.从todos数组删除元素的时候;
4.在控制器中todos数组被改变为其他的数组的时候;

比如下面代码演示的结果;

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

代码演示的结果

上述的情况中,我们对数组对象的是关注点是在对象的属性上,但是实际中往往很多情况我们并不关系对象内的属性是否变化了,而是把数组元素作为一个整体对象处理(比如数组元素个数的变化)。相比上述的代码下面的代码检测的是数组对象元素的变化,而不是对象的isDone属性的变化。在这种情况你可以看看下面例子,在例子中使用键[]代替键@each。从键的变化也可以看出他们的不同之处。

  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.  
  10. WorkerLists = Ember.Object.extend({
  11. // 定义一个Task对象数组
  12. lists: [
  13. Task.create({ isDone: false, name: 'ibeginner.sinaapp.com' }),
  14. Task.create({ isDone: true, name: 'i2cao.xyz' }),
  15. Task.create(),
  16. Task.create({ isDone: true, name: 'ubuntuvim' }),
  17. Task.create({ isDone: true , name: '1527254027@qq.com'}),
  18. Task.create({ isDone: true })
  19. ],
  20.  
  21. index: null,
  22. indexOfSelectedTodo: Ember.computed('index', 'lists.[]', function() {
  23. return this.get('lists').objectAt(this.get('index'));
  24. })
  25. });
  26.  
  27.  
  28. var wl = WorkerLists.create();
  29. // 所有isDone属性值未做任何修改
  30. var index = 1;
  31. wl.set('index', index);
  32. console.log('Get '+wl.get('indexOfSelectedTodo').toString()+' by index ' + index);

代码演示的结果

Ember.computed这个组件中有很多使用键[]实现的方法。当你想创建一个计算属性是数组的时候特别适用。你可以使用Ember.computed.map来构建你的计算属性。

  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. // 为数组赋值
  12. const hamster = Hamster.create({
  13. // 名字chores要与类Hamster定义指定数组的名字一致
  14. chores: ['First Value', 'write more unit tests']
  15. });
  16.  
  17. console.log(hamster.get('excitingChores'));
  18. hamster.get('chores').pushObject("Add item test"); //add an item to chores array
  19. console.log(hamster.get('excitingChores'));

Ember还提供了另外一种方式去定义数组类型的计算属性。

  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. // 为数组赋值
  12. const hamster = Hamster.create({
  13. // 名字chores要与类Hamster定义指定数组的名字一致
  14. chores: ['First Value', 'write more unit tests']
  15. });
  16.  
  17. console.log(hamster.get('excitingChores'));
  18. hamster.get('chores').pushObject("Add item test"); //add an item to chores array
  19. console.log(hamster.get('excitingChores'));
转载本站内容时,请务必注明来自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号