英文原版:https://guides.emberjs.com/v2.13.0/object-model/classes-and-instances/
当你在了解Ember时,你会看到诸如Ember.Component.extend()和DS.Model.extend()之类的代码。在本节你会接触到extend()方法和其他的Ember对象模型的主要方法。
通过在Ember.Object上调用extend()来定义一个新的类:
const Person = Ember.Object.extend({ say(thing) { alert(thing); } });这里定义了一个Person类,并带有一个say()方法。
你可以通过调用extend()方法创建任何类的子类。例如,你或许会想定义一个Ember内建的Ember.Component类的子类:
app/components/todo-item.js export default Ember.Component.extend({ classNameBindings: ['isUrgent'], isUrgent: true });即使你定义了子类,并且覆写的父类中的方法。你仍然可以通过_super属性来调用父类中已经实现了的方法:
const Person = Ember.Object.extend({ say(thing) { alert(`${this.get('name')} says: ${thing}`); } }); const Soldier = Person.extend({ say(thing) { // this will call the method in the parent class (Person#say), appending // the string ', sir!' to the variable `thing` passed in this._super(`${thing}, sir!`); } }); let yehuda = Soldier.create({ name: 'Yehuda Katz' }); yehuda.say('Yes'); // alerts "Yehuda Katz says: Yes, sir!"在一般情况下,你可以在覆写前或覆写后向_super()中传递参数。这将使父类中的方法向正常运行。
覆写Ember Data的序列化器中的normalizeResponse()钩子是个比较常见的例子。
下面的方法使用了动态参数列表:
normalizeResponse(store, primaryModelClass, payload, id, requestType) { // Customize my JSON payload for Ember-Data return this._super(...arguments); }上面的例子中的”…arguments”包含了normalizeResponse参数列表中的所有入参。所以父类中的方法可以正常执行。
一旦你定义好了类,你就可以调用create()方法来创建它的实例。类中定义的所有方法,属性,计算属性在实例中都可用:
const Person = Ember.Object.extend({ say(thing) { alert(`${this.get('name')} says: ${thing}`); } }); let person = Person.create(); person.say('Hello'); // alerts " says: Hello"在创建实例时,你可以为属性赋初始值。向create()方法中传入一个json对象即可:
const Person = Ember.Object.extend({ helloWorld() { alert(`Hi, my name is ${this.get('name')}`); } }); let tom = Person.create({ name: 'Tom Dale' }); tom.helloWorld(); // alerts "Hi, my name is Tom Dale"注意!出于性能考虑,在你在调用create()方法时不能对计算属性,已存在的方法重新定义。同时也不能定义新的方法。你只能操作普通的属性。如果你非要这么做不可,定义个子类吧~~~
为了遵守约定,指向类的属性或者变量都需要使用帕斯卡拼写法,但是指向实例的变量或者属性不用这么弄(驼峰命名法)。
帕斯卡拼写法–描述变量作用所有单词的首字母大写,然后直接连接起来,单词之间没有连接符。例:LastName
当实例被创建的时候,init()方法会自动被调用。这是个做初始配置的理想场所:
const Person = Ember.Object.extend({ init() { alert(`${this.get('name')}, reporting for duty!`); } }); Person.create({ name: 'Stefan Penner' }); // alerts "Stefan Penner, reporting for duty!"如果你在创建一个框架类的子类,比如:Ember.Component,并且你覆写了init(),确定你调用了 this._super(…arguments)。如果你没有这么做,父类可能会做出一些让你匪夷所思的事情。
数组和属性直接定义在Ember.Object的子类中会被该子类的所有实例共享使用:
const Person = Ember.Object.extend({ shoppingList: ['eggs', 'cheese'] }); Person.create({ name: 'Stefan Penner', addItem() { this.get('shoppingList').pushObject('bacon'); } }); Person.create({ name: 'Robert Jackson', addItem() { this.get('shoppingList').pushObject('sausage'); } }); // Stefan and Robert both trigger their addItem. // They both end up with: ['eggs', 'cheese', 'bacon', 'sausage']为了避免此情况,你可以在init()中初始化数组和对象属性。这样能确保每个实例都有自己的数组和属性:
const Person = Ember.Object.extend({ init() { this.set('shoppingList', ['eggs', 'cheese']); } }); Person.create({ name: 'Stefan Penner', addItem() { this.get('shoppingList').pushObject('bacon'); } }); Person.create({ name: 'Robert Jackson', addItem() { this.get('shoppingList').pushObject('sausage'); } }); // Stefan ['eggs', 'cheese', 'bacon'] // Robert ['eggs', 'cheese', 'sausage']如果要操作对象属性,使用get()和set() 访问器方法。
const Person = Ember.Object.extend({ name: 'Robert Jackson' }); let person = Person.create(); person.get('name'); // 'Robert Jackson' person.set('name', 'Tobias Fünke'); person.get('name'); // 'Tobias Fünke'请确保使用这些方法。否则,计算属性不会重新计算,观察者不会被处罚,模板也不会重新渲染。
本节完