Javascript 如何使用knockoutJS对象实现heritage

Javascript 如何使用knockoutJS对象实现heritage,javascript,jquery,knockout.js,Javascript,Jquery,Knockout.js,我有一个由项目对象、文本对象和设置对象组成的模型。设置对象可以同时保存项目和文本的值 文本始终与项目耦合。因此,它应该继承项目s设置(如果有)。但是,如果文本本身具有设置,则用户应该能够选择使用项目默认设置还是特定于文本的设置 我在项目中遇到的问题是,更新文本本地设置也会更新项目默认设置。我想这与可观测的关系有关,但到目前为止我还无法找到这种联系 这是我的密码: Text = function (data) { var self = this; self.textID = da

我有一个由
项目
对象、
文本
对象和
设置
对象组成的模型。
设置
对象可以同时保存
项目
文本
的值

文本
始终与
项目
耦合。因此,它应该继承
项目
s
设置
(如果有)。但是,如果
文本
本身具有
设置
,则用户应该能够选择使用项目默认设置还是特定于文本的
设置

我在项目中遇到的问题是,更新文本本地设置也会更新项目默认设置。我想这与可观测的关系有关,但到目前为止我还无法找到这种联系

这是我的密码:

Text = function (data) {
    var self = this;

    self.textID = data.textID;
    self.title = ko.observable(data.title);
    self.projectID = data.projectID;

    // settings
    self.settings = ko.observable();          // initiated with "each" loop hook-up in viewmodel.
    self.project = ko.observable();            // initiated with "each" loop hook-up in viewmodel.
    self.projectSettings = ko.computed(function () {
        var project = self.project();
        if (project) {
            var proset = project.settings();
            return proset;
        }
        return null;
    });
    self.useProjectSettings = ko.observable(data.useProjectSettings || true);
    self.hasLocalSettings = ko.observable(false); // initiated with each loop hook-up in viewmodel.

    self.activeSettings = ko.computed(function () {
        return self.useProjectSettings() ? self.projectSettings() : self.settings();
    });

    return self;
};

Project = function (data) {
    var self = this;

    self.projectID = data.projectID;
    self.title = ko.observable(data.title);

    // settings
    self.settings = ko.observable();

    return self;
};

Setting = function (data) {
    var self = this;

    self.settingID = data.settingID;
    self.projectID = data.projectID;
    self.textID = data.textID;

    self.isVisible = ko.observable(data.isVisible);
    self.isProjectDefault = ko.observable(data.isProjectDefault || true);

    return self;
};

ViewModel = function (myprojects, mysettings, mytexts) {
    var self = this,
        koEach = ko.utils.arrayForEach, koFirst = ko.utils.arrayFirst, koFilter = ko.utils.arrayFilter;

    self.selectedText = ko.observable();

    //data - load
    self.Projects = ko.observableArray(
         ko.utils.arrayMap(myprojects, function (item) {
             return new Project(item);
         }));
    self.Settings = ko.observableArray(
        ko.utils.arrayMap(mysettings, function (item) {
            return new Setting(item);
        }));
    self.Texts = ko.observableArray(
         ko.utils.arrayMap(mytexts, function (item) {
             return new Text(item);
         }));

    //alert("self.Projects()[0].projectID=" + self.Projects()[0].projectID );


    // hook up 'settings' on 'project'
    koEach(self.Settings(), function (s) {

        if (s.isProjectDefault()) {
            var project = koFirst(self.Projects(), function (p) {
                return p.projectID === s.projectID;
            });
            if (project) {
                project.settings(s);
            }
        }
    });

    //alert("self.Texts()[0].textID=" + self.Texts()[0].textID + ", self.Texts()[0].title()=" + self.Texts()[0].title() );

    //hook up 'project' on 'texts'
    koEach(self.Texts(), function (t) {
        var project = koFirst(self.Projects(), function (p) {
            return p.projectID === t.projectID;
        });
        t.project(project);
        // initiate default publishingSettings for textbatch
        var initsettings = project.settings();
        t.settings(initsettings);
    });

    // hook up 'settings' on 'text'
    koEach(self.Settings(), function (s) {
        if (!s.isProjectDefault()) {
            var text = koFirst(self.Texts(), function (t) {
                return t.textID === s.textID;
            });
            if (text) {
                text.settings(s);
            }
        }
    });
};



// console log
var consoleLine = "<p class=\"console-line\"></p>";
console = {
    log: function (text) {
        $("#console-log").append($(consoleLine).html(text));
    }
};

// input
var projects = [{ projectID: 0, title: 'project 0' }, { projectID: 1, title: 'project 1' }];
var settings = [
    { settingID: 0, projectID: 1, textID: null, isVisible: true, isProjectDefault: true },
    { settingID: 1, projectID: null, textID: 0, isVisible: true, isProjectDefault: false },
    { settingID: 2, projectID: 1, textID: 1, isVisible: false, isProjectDefault: false }
];
var texts = [{ textID: 0, projectID: 0, title: 'first text' }, { textID: 1, projectID: 1, title: 'second text' }];

// binding
ko.applyBindings(new ViewModel(projects, settings, texts));
Text=函数(数据){
var self=这个;
self.textID=data.textID;
self.title=ko.可观察(data.title);
self.projectID=data.projectID;
//背景
self.settings=ko.observable();//通过viewmodel中的“each”循环连接启动。
self.project=ko.observable();//通过viewmodel中的“each”循环连接启动。
self.projectSettings=ko.computed(函数(){
var project=self.project();
国际单项体育联合会(项目){
var proset=project.settings();
返回进程集;
}
返回null;
});
self.useProjectSettings=ko.observable(data.useProjectSettings | | true);
self.hasLocalSettings=ko.observable(false);//在viewmodel中使用每个循环连接启动。
self.activeSettings=ko.computed(函数(){
返回self.useProjectSettings()?self.projectSettings():self.settings();
});
回归自我;
};
项目=功能(数据){
var self=这个;
self.projectID=data.projectID;
self.title=ko.可观察(data.title);
//背景
self.settings=ko.observable();
回归自我;
};
设置=功能(数据){
var self=这个;
self.settingID=data.settingID;
self.projectID=data.projectID;
self.textID=data.textID;
self.isVisible=ko.observable(data.isVisible);
self.isProjectDefault=ko.observable(data.isProjectDefault | | true);
回归自我;
};
ViewModel=函数(MyProject、mysettings、MyText){
var self=这个,
koEach=ko.utils.arrayForEach,koFirst=ko.utils.arrayFirst,koFilter=ko.utils.arrayFilter;
self.selectedText=ko.observable();
//数据加载
self.Projects=ko.array(
ko.utils.arrayMap(我的项目,功能(项目){
返回新项目(项);
}));
self.Settings=ko.observearray(
ko.utils.arrayMap(mysettings,function(项)){
返回新设置(项目);
}));
self.text=ko.array(
ko.utils.arrayMap(MyText,函数(项)){
返回新文本(项目);
}));
//警报(“self.Projects()[0].projectID=“+self.Projects()[0].projectID”);
//在“项目”上连接“设置”
koEach(self.Settings(),函数){
如果(s.isProjectDefault()){
var project=koFirst(self.Projects(),函数(p){
返回p.projectID==s.projectID;
});
国际单项体育联合会(项目){
项目设置;
}
}
});
//警报(“self.text()[0].textID=“+self.text()[0].textID+”,self.text()[0].title()=“+self.text()[0].title());
//在“文本”上连接“项目”
koEach(self.text(),函数(t){
var project=koFirst(self.Projects(),函数(p){
返回p.projectID==t.projectID;
});
t、 项目(项目);
//启动textbatch的默认发布设置
var initsettings=project.settings();
t、 设置(初始设置);
});
//在“文本”上连接“设置”
koEach(self.Settings(),函数){
如果(!s.isProjectDefault()){
var text=koFirst(self.text(),函数(t){
返回t.textID==s.textID;
});
如果(文本){
文本。设置;
}
}
});
};
//控制台日志
var consoleLine=“

”; 控制台={ 日志:函数(文本){ $(“#控制台日志”).append($(consoleLine.html(text)); } }; //输入 var projects=[{projectID:0,title:'project0'},{projectID:1,title:'project1'}]; 变量设置=[ {settingID:0,projectID:1,textID:null,isVisible:true,isProjectDefault:true}, {settingID:1,projectID:null,textID:0,isVisible:true,isProjectDefault:false}, {settingID:2,projectID:1,textID:1,isVisible:false,isProjectDefault:false} ]; var text=[{textID:0,projectID:0,title:'first text'},{textID:1,projectID:1,title:'second text'}]; //装订 应用绑定(新的视图模型(项目、设置、文本));
这是我的HTML:

<select data-bind="options: $root.Texts, optionsCaption: 'choose...', optionsText: 'title', value: selectedText"></select>
<br/>

Selected:   <span data-bind="text: $root.selectedText().title"></span><br>
Selected2:   <span data-bind="text: $root.selectedText().title"></span><br>
TextID:   <span data-bind="text: selectedText().textID"></span><br>
<hr/>    

<div data-bind="with: $root.selectedText">  
    <h2 data-bind="text:title"></h2>
    <div class="form-group">
       <div class="checkbox">
            <label>
                <input type="checkbox" data-bind="checked: useProjectSettings" />Use project settings
            </label>
        </div>
    </div>
    Settings for text '<span data-bind="text: title"></span>' (id='<span data-bind="value: textID"></span>').<br/><br/>    
    <div class="pubset" data-bind="css: {'unabled' : useProjectSettings() }"> 
       <div class="form-group">
           <div class="checkbox">
               <label>
                   <input type="checkbox" data-bind="enable: !useProjectSettings(),checked: activeSettings().isVisible"/>
                   Show text
               </label>
           </div>
        </div>
    </div>
</div>


已选择:
已选择2:
TextID:

使用项目设置 文本“”的设置(id=“”)。

显示文本

这里的示例代码似乎还有另一个问题,因为它没有进入第二个
节点。Fiddle。

我觉得您对对象结构的书面解释与实际代码结构不同。传入的数据结构似乎只与整数ID相关。是否可以通过嵌套属性实际按层次关系关联数据?那么你就不需要查找属性了。如果属性冒泡了,那就意味着你的可观察对象被引用了。因此,在分配可观察的directl之前,创建一个新副本