簡體   English   中英

Ember.Object實例中的必需屬性(構造函數args)

[英]Required properties (constructor args) in Ember.Object instances

在Ember中,假設我有一個名為FoodStuff的對象,它有一些屬性:

export default Ember.Object.extend({
    name: null,     // REQUIRED: 'Slice of Apple Pie'
    calories: null, // OPTIONAL: int: eg. 250
    category: null, // REQUIRED: 'Pastry'
    rating: null    // OPTIONAL: int: 1-5
});

如何在Ember中編寫“構造函數”,要求在實例化時提供“名稱”和“類別”屬性?

Angular似乎用相當簡單的語法來解決這個問題:

.factory('User', function (Organisation) {

  /**
   * Constructor, with class name
   */
  function User(firstName, lastName, role, organisation) {
    // Public properties, assigned to the instance ('this')
    this.firstName = firstName;
    ...

具有JavaScript類的Angular模型對象

Ember有類似的東西嗎? 目前我的所有類都在頂部看到,有一堆初始為null的屬性,調用者可能正確設置也可能沒有 在構建時(我正在使用ember-cli )我希望通過ember build階段將構造函數需求的更改捕獲到下游。

據我所知,在Ember中沒有本地方法可以做到這一點。 但沒有什么是不可能的! 你可以調整Ember來處理這個案子。 只需添加初始化程序:

/initialsizers/extend-ember.js

import Ember from 'ember';

export function initialize() {

  Ember.Object.reopen({

    /**
     * @prop {Array} - array of required properties
     */
    requiredAttrs: [],

    /**
     * Validates existance of required properties
     *
     * @param {String} attr - attribute name
     * @param {*} value - value of the property
     * @throws {Error} in case when required property is not set
     */
    _validateExistance(attr, value) {
      if (this.requiredAttrs.contains(attr) && typeof value === "undefined") {
        throw new Error("Attribute " + attr + " can't be empty!");
      }
    },

    /**
     * Sets value of a property and validates existance of required properties
     *
     * @override 
     */
    set(key, value) {
      this._validateExistance(key, value);
      return this._super(key, value);
    }

  });

  Ember.Object.reopenClass({

    /**
     * Creates object instance and validates existance of required properties
     *
     * @override
     */
    create(attrs) {
      let obj = this._super(attrs);
      if (attrs) {
        obj.requiredAttrs.forEach((key) => {
          obj._validateExistance(key, attrs[key]);
        });
      }
      return obj;
    }

  });

}

export default {
  name: 'extend-ember',
  initialize: initialize
};

然后,您可以在任何類上使用requiredAttrs屬性來定義所需的屬性。 如果您嘗試創建具有空必需屬性的實例,或者嘗試將空值設置為required屬性,則會拋出異常。

let MyModel = Ember.Object.extend({
  prop1: null,
  prop2: null,
  requiredAttrs: ['prop2']
});

let ChildModel = MyModel.extend({
  prop3: null,
  requiredAttrs: ['prop2', 'prop3']
});

// throws exception
let obj1 = MyModel.create({
  prop1: 'val1'
});

// no exception
let obj2 = MyModel.create({
  prop2: 'val2'
});

// throws exception
obj2.set('prop2', undefined);

// throws exception
let obj3 = ChildModel.create({
  prop3: 'val3'
});

// no exception
let obj4 = ChildModel.create({
  prop2: 'val2',
  prop3: 'val3'
});

它也適用於DS.ModelDS.Model其他Ember實體,因為它們都擴展了Ember.Object

要進行實例化時間(運行時)檢查,您需要覆蓋init方法:

init() {
    this._super();
    Ember.assert('Name cannot be empty', name);
    // ...
}

為了讓他們在建設時被抓住,我不確定這樣做的好方法。 您可以使用某種工具向Javascript(Typescript和Flow想到)添加靜態類型,這可能會在實例化這些對象時強制執行這些屬性。 您也可以編寫一個自定義工具(如ESLint插件)來檢查它,但這可能比它的價值更難。 您最好使用運行時解決方案和體面的測試覆蓋率。


這是一個擁有自己的create()方法的例子。

SomeClass.reopenClass({
    create(name, category, calories = null, rating = null) {
        // Validate your properties
        Ember.assert('Name cannot be empty', name);
        // ...

        // Create the object
        var obj = this._super({ name, category, calories, rating });

        // Do any other setup/validation

        // Return the object
        return obj;
    }
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM