Knockout - 通过在对象上设置 属性 来更改对象的 'subclass'
Knockout - change an object's 'subclass' by setting a property on it
在 Knockout 中,我有一个 Setting
实体数组,这些实体可能具有不同的 类型 (即设置实体的 'subclasses')。这些类型是动态的,它们可以在 UI 中由用户更改。根据设置实体的类型,它需要不同的对象属性,并使其他属性变得多余。
我目前正在做的(我想改变的)是定义一个设置构造函数,它具有所有设置类型所需的所有属性;使构造函数非常庞大,并包含许多不必要的属性。保存应用程序数据时,我 'ignore' 不应在根据其类型设置实例的属性。
我已经在 this fiddle 中尝试过,使用 type
属性 上的订阅在类型更改时添加/删除属性。我想知道在 KnockoutJS 中是否有可能 在 运行-time 期间可靠地更改对象的属性(即订阅是否总是在模板更新之前触发?),这会对性能产生任何[积极]影响吗?。或者这种方法是完全错误的,我应该用子类实例替换整个对象(如果是这样,订阅不会丢失)吗?
编辑: 依赖属性是实际数据(因此它们应该保存到它们的模型中,而不仅仅是在视图中可用)。我已经尝试过组件方法,但以后如何检索它们的属性? http://jsfiddle.net/kevinvanlierde/zmx3u4an/1/
使用在您的设置编辑器中绑定但由每个单独的子类实例拥有的组件。
<div data-bind="foreach: settings">
<select data-bind="options: $root.types, value: type"></select>
<input type="text" data-bind="textInput: value"/>
<div data-bind="component: { name: componentName, params: componentParams }"></div>
</div>
颜色设置的示例组件 name/params。对于不同的设置子类,这些属性会有所不同。
this.componentName = 'color-viewer';
this.componentParams = {
colorText: this.value,
};
使用这种方法,更改当前设置 "type" 需要您将一个设置子类实例替换为另一个。这在微不足道的情况下可能会很麻烦,但是通过单一责任保持模型的小型化是有好处的。
为了解决保存属性的问题,我重新编写了组件代码。有些成员(主要是计算的)只用于视图,不应该保存,所以我把 save-able 的东西放在 "data" 成员中:
function Setting(params) {
var self = this;
// What getData fetches
self.data = {
type: ko.observable(params.type),
value: ko.observable(params.value || '')
};
self.data.type.subscribe(function (value) {
// Give the conversion a little time
setTimeout(function () {
console.log("GetData:", self.getData());
}, 30);
});
}
每个专用类型都将把它的特殊成员添加到基础 object 中,并将添加一个方法 toSetting
以将其恢复为基础 object 类型。基本类型在其原型中有一个 do-nothing 版本的 toSetting
,因此在类型转换器中首先调用 toSetting
始终是安全的。
我向 Title 类型添加了一个 headingSize
参数,并使其确定文本显示的标题大小。
function toTitle(setting) {
var self = setting;
var data = setting.data;
var value = data.value();
self.toSetting();
data.headingSize = ko.observable(4);
self.capitalized = ko.computed(function () {
return value ? value.slice(0, 1).toUpperCase() + value.slice(1) : '';
});
self.headerText = ko.computed(function () {
return '<h' + data.headingSize() + '>' + self.capitalized() + '</h' + data.headingSize() + '>';
});
self.toSetting = function () {
delete self.data.headingSize;
delete self.capitalized;
delete self.toSetting;
};
return self;
}
我是这样注册的:
ko.components.register('title', {
viewModel: toTitle,
template: '<select data-bind="options:$root.sizes, value: data.headingSize"></select><div data-bind="html:headerText"></div>'
});
我在设置中添加了一个按钮"save",它会在页面底部显示将要保存的内容。
在 Knockout 中,我有一个 Setting
实体数组,这些实体可能具有不同的 类型 (即设置实体的 'subclasses')。这些类型是动态的,它们可以在 UI 中由用户更改。根据设置实体的类型,它需要不同的对象属性,并使其他属性变得多余。
我目前正在做的(我想改变的)是定义一个设置构造函数,它具有所有设置类型所需的所有属性;使构造函数非常庞大,并包含许多不必要的属性。保存应用程序数据时,我 'ignore' 不应在根据其类型设置实例的属性。
我已经在 this fiddle 中尝试过,使用 type
属性 上的订阅在类型更改时添加/删除属性。我想知道在 KnockoutJS 中是否有可能 在 运行-time 期间可靠地更改对象的属性(即订阅是否总是在模板更新之前触发?),这会对性能产生任何[积极]影响吗?。或者这种方法是完全错误的,我应该用子类实例替换整个对象(如果是这样,订阅不会丢失)吗?
编辑: 依赖属性是实际数据(因此它们应该保存到它们的模型中,而不仅仅是在视图中可用)。我已经尝试过组件方法,但以后如何检索它们的属性? http://jsfiddle.net/kevinvanlierde/zmx3u4an/1/
使用在您的设置编辑器中绑定但由每个单独的子类实例拥有的组件。
<div data-bind="foreach: settings">
<select data-bind="options: $root.types, value: type"></select>
<input type="text" data-bind="textInput: value"/>
<div data-bind="component: { name: componentName, params: componentParams }"></div>
</div>
颜色设置的示例组件 name/params。对于不同的设置子类,这些属性会有所不同。
this.componentName = 'color-viewer';
this.componentParams = {
colorText: this.value,
};
使用这种方法,更改当前设置 "type" 需要您将一个设置子类实例替换为另一个。这在微不足道的情况下可能会很麻烦,但是通过单一责任保持模型的小型化是有好处的。
为了解决保存属性的问题,我重新编写了组件代码。有些成员(主要是计算的)只用于视图,不应该保存,所以我把 save-able 的东西放在 "data" 成员中:
function Setting(params) {
var self = this;
// What getData fetches
self.data = {
type: ko.observable(params.type),
value: ko.observable(params.value || '')
};
self.data.type.subscribe(function (value) {
// Give the conversion a little time
setTimeout(function () {
console.log("GetData:", self.getData());
}, 30);
});
}
每个专用类型都将把它的特殊成员添加到基础 object 中,并将添加一个方法 toSetting
以将其恢复为基础 object 类型。基本类型在其原型中有一个 do-nothing 版本的 toSetting
,因此在类型转换器中首先调用 toSetting
始终是安全的。
我向 Title 类型添加了一个 headingSize
参数,并使其确定文本显示的标题大小。
function toTitle(setting) {
var self = setting;
var data = setting.data;
var value = data.value();
self.toSetting();
data.headingSize = ko.observable(4);
self.capitalized = ko.computed(function () {
return value ? value.slice(0, 1).toUpperCase() + value.slice(1) : '';
});
self.headerText = ko.computed(function () {
return '<h' + data.headingSize() + '>' + self.capitalized() + '</h' + data.headingSize() + '>';
});
self.toSetting = function () {
delete self.data.headingSize;
delete self.capitalized;
delete self.toSetting;
};
return self;
}
我是这样注册的:
ko.components.register('title', {
viewModel: toTitle,
template: '<select data-bind="options:$root.sizes, value: data.headingSize"></select><div data-bind="html:headerText"></div>'
});
我在设置中添加了一个按钮"save",它会在页面底部显示将要保存的内容。