Javascript Ember.Object实例中的必需属性(构造函数参数)
在Ember中,假设我有一个名为Javascript Ember.Object实例中的必需属性(构造函数参数),javascript,ember.js,Javascript,Ember.js,在Ember中,假设我有一个名为foody的对象,它有一些属性: 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:
foody
的对象,它有一些属性:
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中编写“构造函数”,要求在实例化时提供“name”和“category”属性
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;
...
灰烬有类似的东西吗?目前,我的所有类都如顶部所示,具有一组最初为null的属性,这些属性可能由调用方正确设置,也可能未正确设置。在构建时(我使用的是
ember cli
),我希望构造函数需求的更改能够通过JSHint的ember构建
阶段被下游捕获。要进行实例化时间(运行时)检查,您需要覆盖该方法:
为了让他们在构建时被抓到,我不确定有什么好方法可以做到这一点。您可以使用某种工具将静态类型添加到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;
}
});
据我所知,在余烬没有本地的方式来做这件事。但是没有什么是不可能的!你可以稍微调整余烬来处理这个问题。只需添加一个初始值设定项: /initializers/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
属性来定义所需的属性。如果您尝试使用空的必需属性创建实例,或者尝试将空值设置为必需属性,则会引发异常
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.Model
和其他现成的余烬实体,因为它们都扩展了Ember.Object
我希望有一种方法可以删除或隐藏create()
函数,而不是要求子类编写自己的,决定需要哪些init参数。如果需要,您可以这样做,但请记住,您最终必须调用create()
,以便Ember正确设置所有内容。我将用一个例子更新我的答案。虽然这是一个运行时检查,我正在寻找一个build/JSHint时间检查,但这似乎是最接近的。谢谢
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'
});