May 09, 2021 Ember.js Reference documents
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.
Person = Ember.Object.extend({
firstName: null,
lastName: null,
// fullName 就是一个计算属性
fullName: Ember.computed('firstName', 'lastName', function() {
return this.get('firstName') + ", " + this.get('lastName');
})
});
// 实例化同时传入参数
var piter = Person.create({
firstName: 'chen',
lastName: 'ubuntuvim'
});
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.
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.
Person = Ember.Object.extend({
firstName: null,
lastName: null,
age: null,
county: null,
// fullName 就是一个计算属性
fullName: Ember.computed('firstName', 'lastName', function() {
return this.get('firstName') + ", " + this.get('lastName');
}),
description: Ember.computed('fullName', 'age', 'county', function() {
return this.get('fullName') + " age " + this.get('age') + " county " + this.get('county');
})
});
// 实例化同时传入参数
var piter = Person.create({
firstName: 'chen',
lastName: 'ubuntuvim',
age: 25,
county: 'china'
});
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.
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
// 重写计算属性的get、set方法
Person = Ember.Object.extend({
firstName: null,
lastName: null,
// 重写计算属性fullName的get、set方法
fullName: Ember.computed('firstName', 'lastName', {
get(key) {
return this.get('firstName') + "," + this.get('lastName');
},
set(key, value) {
// 这个官方文档使用的代码,但是我运行的时候出现 Uncaught SyntaxError: Unexpected token [ 这个错误,不知道是否是缺少某个文件,后续会补上;
// console.log("value = " + value);
// var [ firstName, lastName ] = value.split(/\s+/);
var firstName = value.split(/\s+/)[0];
var lastName = value.split(/\s+/)[1];
this.set('firstName', firstName);
this.set('lastName', lastName);
}
}),
// 对于普通的属性无法重写get、set方法
// firstName: Ember.computed('firstName', {
// get(key) {
// return this.get('firstName') + "@@";
// },
// set(key, value) {
// this.set('firstName', value);
// }
// })
});
var jack = Person.create();
jack.set('fullName', "james kobe");
console.log(jack.get('firstName'));
console.log(jack.get('lastName'));
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
export default Ember.Controller.extend({
todos: [
Ember.Object.create({ isDone: true }),
Ember.Object.create({ isDone: false }),
Ember.Object.create({ isDone: true })
],
remaining: Ember.computed('[email protected]', function() {
var todos = this.get('todos');
return todos.filterBy('isDone', false).get('length');
})
});
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;
Task = Ember.Object.extend({
isDone: false // 默认为false
});
WorkerLists = Ember.Object.extend({
// 定义一个Task对象数组
lists: [
Task.create({ isDone: false }),
Task.create({ isDone: true }),
Task.create(),
Task.create({ isDone: true }),
Task.create({ isDone: true }),
Task.create({ isDone: true }),
Task.create({ isDone: false }),
Task.create({ isDone: true })
],
remaining: Ember.computed('[email protected]', function() {
var lists = this.get('lists');
// 先查询属性isDone值为false的对象,再返回其数量
return lists.filterBy('isDone', false).get('length');
})
});
// 如下代码使用到的API请查看:http://emberjs.com/api/classes/Ember.MutableArray.html
var wl = WorkerLists.create();
// 所有isDone属性值未做任何修改
console.log('1,>> Not complete lenght is ' + wl.get('remaining')); // output 3
var lists = wl.get('lists'); // 得到对象内的数组
// ----- 演示第一种情况: 1. 在todos数组中任意一个对象的isDone属性值发生变化的时候;
// 修改数组一个元素的isDone的 值
var item1 = lists.objectAt(3); // 得到第4个元素 objectAt()方法是Ember为我们提供的
// console.log('item1 = ' + item1);
item1.set('isDone', false);
console.log('2,>> Not complete lenght is ' + wl.get('remaining')); // output 4
// --------- 2. 往todos数组新增元素的时候;
lists.pushObject(Task.create({ isDone: false })); //新增一个isDone为false的对象
console.log('3,>> Not complete lenght is ' + wl.get('remaining')); // output 5
// --------- 3. 从todos数组删除元素的时候;
lists.removeObject(item1); // 删除了一个元素
console.log('4,>> Not complete lenght is ' + wl.get('remaining')); // output 4
// --------- 4. 在控制器中todos数组被改变为其他的数组的时候;
// 创建一个Controller
TodosController = Ember.Controller.extend({
// 在控制器内定义另外一个Task对象数组
todosInController: [
Task.create({ isDone: false }),
Task.create({ isDone: true })
],
// 使用键”@each.isDone“遍历得到的filterBy()方法过滤后的对象的isDone属性
remaining: function() {
// remaining()方法返回的是控制器内的数组
return this.get('todosInController').filterBy('isDone', false).get('length');
}.property('@each.isDone') // 指定遍历的属性
});
todosController = TodosController.create();
var count = todosController.get('remaining');
console.log('5,>> Not complete lenght is ' + count); // output 1
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.
Task = Ember.Object.extend({
isDone: false, // 默认为false
name: 'taskName',
// 为了显示结果方便,重写toString()方法
toString: function() {
return '[name = '+this.get('name')+', isDone = '+this.get('isDone')+']';
}
});
WorkerLists = Ember.Object.extend({
// 定义一个Task对象数组
lists: [
Task.create({ isDone: false, name: 'ibeginner.sinaapp.com' }),
Task.create({ isDone: true, name: 'i2cao.xyz' }),
Task.create(),
Task.create({ isDone: true, name: 'ubuntuvim' }),
Task.create({ isDone: true , name: '[email protected]'}),
Task.create({ isDone: true })
],
index: null,
indexOfSelectedTodo: Ember.computed('index', 'lists.[]', function() {
return this.get('lists').objectAt(this.get('index'));
})
});
var wl = WorkerLists.create();
// 所有isDone属性值未做任何修改
var index = 1;
wl.set('index', index);
console.log('Get '+wl.get('indexOfSelectedTodo').toString()+' by index ' + index);
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.
const Hamster = Ember.Object.extend({
chores: null,
excitingChores: Ember.computed('chores.[]', function() { //告诉Ember chores是一个数组
return this.get('chores').map(function(chore, index) {
//return `${index} --> ${chore.toUpperCase()}`; // 可以使用${}表达式,并且在表达式内可以直接调用js方法
return `${chore}`; //返回元素值
});
})
});
// 为数组赋值
const hamster = Hamster.create({
// 名字chores要与类Hamster定义指定数组的名字一致
chores: ['First Value', 'write more unit tests']
});
console.log(hamster.get('excitingChores'));
hamster.get('chores').pushObject("Add item test"); //add an item to chores array
console.log(hamster.get('excitingChores'));
Ember
provides another way to define the calculated properties of array types.
const Hamster = Ember.Object.extend({
chores: null,
excitingChores: Ember.computed('chores.[]', function() {
return this.get('chores').map(function(chore, index) {
//return `${index} --> ${chore.toUpperCase()}`; // 可以使用${}表达式,并且在表达式内可以直接调用js方法
return `${chore}`; //返回元素值
});
})
});
// 为数组赋值
const hamster = Hamster.create({
// 名字chores要与类Hamster定义指定数组的名字一致
chores: ['First Value', 'write more unit tests']
});
console.log(hamster.get('excitingChores'));
hamster.get('chores').pushObject("Add item test"); //add an item to chores array
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!!