删除-更改对象's '子类'通过在上面设置一个属性

Knockout - change an object's 'subclass' by setting a property on it

本文关键字:设置 属性 一个 在上面 子类 对象 删除      更新时间:2023-09-26

在Knockout中,我有一个Setting实体数组,可能具有不同的类型(即:设置实体的"子类")。这些类型是动态的,用户可以在UI中更改它们。根据设置实体的类型不同,它需要不同的对象属性,并使其他属性变得多余。

我目前正在做的(我想改变),是定义一个设置构造函数,它具有所有设置类型所需的所有属性;使构造函数非常庞大,并包含许多不必要的属性。当应用数据被保存时,我"忽略"那些不应该在根据它们的类型设置实例上的属性。

我已经给了它一个尝试在这个fiddle,使用订阅的type属性添加/删除属性的类型更改。我想知道是否有可能在KnockoutJS 在运行时期间可靠地改变对象的属性(即订阅在模板更新之前总是会触发吗?)是否会对性能产生任何[积极]影响?或者这种方法是完全错误的,我应该用子类实例替换整个对象(如果是这样,订阅不会丢失吗)?

EDIT:依赖属性是实际数据(因此它们应该保存到它们的模型中,而不仅仅是在视图中可用)。我已经尝试了组件方法,但我如何检索他们的属性以后?http://jsfiddle.net/kevinvanlierde/zmx3u4an/1/

为了保存属性,我重新编写了组件代码。有些成员(主要是计算)仅用于视图,不应该保存,因此我将可保存的内容放在"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);
    });
}

每个专门化类型都将其特殊成员添加到基对象中,并添加一个方法toSetting,将其还原为基对象类型。基本类型在其原型中有一个不做任何事情的toSetting版本,因此在类型转换器中首先调用toSetting总是安全的。

我给标题类型添加了一个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>'
});

我添加了一个按钮来"保存"设置,它会在页面底部显示要保存的内容。

http://jsfiddle.net/1kfvesq3/3/

使用在设置编辑器中绑定但由每个单独的子类实例拥有的组件。

<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>

颜色设置的组件名称/参数示例。这些属性对于不同的设置子类是不同的。

this.componentName = 'color-viewer';
this.componentParams = {
    colorText: this.value,
};

使用这种方法,更改当前设置"类型"将需要您用另一个设置子类实例替换一个设置子类实例。这在一些琐碎的情况下可能是一个麻烦,但是保持你的模型小而责任单一是有好处的。