淘汰赛 - 改变对象的子类'通过在其上设置属性

时间:2015-06-04 21:32:51

标签: javascript knockout.js subclass

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

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

我已经在this fiddle中尝试了一下,使用Setting属性上的订阅来添加/删除类型更改的属性。我想知道在KnockoutJS中是否有可能在运行时期间可靠地更改对象的属性(即订阅是否会在模板更新之前始终触发?)并且这样做对绩效有任何[正面]影响?。或者这种方法是完全错误的,我应该用子类实例替换整个对象(如果是这样,赢得订阅会丢失)?

编辑:从属属性是实际数据(因此它们应保存到模型中,不仅在视图中可用)。我已尝试过组件方法,但如何在以后检索其属性? http://jsfiddle.net/kevinvanlierde/zmx3u4an/1/

2 个答案:

答案 0 :(得分: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>

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

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

使用这种方法,更改当前设置&#34;键入&#34;会要求您将一个设置子类实例替换为另一个。这可能是一个简单的案件中的麻烦,但是保持你的模型只有一个单一的责任有其优势。

答案 1 :(得分:1)

为了解决保存属性的问题,我重新编写了组件代码。一些成员(主要是计算机)仅用于视图,不应保存,因此我将可保存的内容放在“数据”成员中:

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始终是安全的。

我在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>'
});

我添加了一个“保存”设置的按钮,显示将保存在页面底部的内容。

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