#2 类与实例

xiaoxiao2021-02-28  123

英文原版: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'

请确保使用这些方法。否则,计算属性不会重新计算,观察者不会被处罚,模板也不会重新渲染。

本节完

转载请注明原文地址: https://www.6miu.com/read-26243.html

最新回复(0)