Javascript 一个DOM树中的多个淘汰模型绑定

Javascript 一个DOM树中的多个淘汰模型绑定,javascript,jquery,html,knockout.js,Javascript,Jquery,Html,Knockout.js,假设我们有一个DOM树: 所以我们可以把模型绑定到树上 ko.applyBindings(model, document.getElementById('rootNode')); 但如果我们想将子节点1绑定到其他模型呢?如果只是写 ko.applyBindings(model, document.getElementById('subNode1')); 我想这不起作用,因为第一个数据绑定与第二个数据绑定重叠 现在我为什么要这么做。我有一个包含几个独立组件的lib,我使用Knockout实

假设我们有一个DOM树:


所以我们可以把模型绑定到树上

ko.applyBindings(model, document.getElementById('rootNode'));
但如果我们想将子节点1绑定到其他模型呢?如果只是写

ko.applyBindings(model, document.getElementById('subNode1'));
我想这不起作用,因为第一个数据绑定与第二个数据绑定重叠

现在我为什么要这么做。我有一个包含几个独立组件的lib,我使用Knockout实现了它。组件如下所示:

function ComboBox(container)
{
    this.name = new ko.observable();
    this.someValue1 = new ko.observable();
    this.someValue2 = new ko.observable();

    ko.applyBindings(this, document.getElementById(container));
}
不幸的是,我不能写:

SomeBigComponent('rootNode');

ComboBox('subNode');

我怎样才能解决这个问题?第二个问题是这样组织代码好吗?

处理这种情况的典型方法是创建一个主视图模型,它是子视图模型的容器

所以,你可以

var viewModel = {
  mainModel: { 
     ...
  },
  comboModel: {
     ...
  }
};
然后,如果您使用的是1.3 beta版,您可以执行以下操作:

 <div id="subNode1" data-bind="with: comboModel > 
    <span data-bind="..." > </span>
 </div>
 <div id="subNode1" data-bind="template: { name: 'comboTmpl', data: comboModel }" ></div>

 <script id="comboTmpl" type="text/html">
    <span data-bind="..." > </span>
 </script>

您还可以向视图模型传递一个模式参数,并根据模式设置一个用于绑定的数据属性,在您的ui中,您将根据模式属性知道要使哪个ui可见,事实上,这本身就是一个绑定

e、 g-请在服务器上使用适当的/虚拟web api方法

        <script type="text/javascript" src="../../Scripts/jquery-1.7.1.min.js"></script>
        <script type="text/javascript" src="../../Scripts/knockout.js"></script>
        <script type="text/javascript" src="../../Scripts/knockout.mapping-latest.js"></script>
        <script type="text/javascript">
            $(function () {

                //allows a view to submit info about a new product
                //and get product data
                function viewModel(mode) {
                    var self = this;
                    self.mode = mode;
                    if (self.mode == 'i') {
        self.data = ko.observable(ko.mapping.fromJS({ ProductID: 0, ShortName:[NEW PRODUCT]', SupplierCode: '', UnitsInBox: 0, CostPerUnit: 0, BoxSalePrice: 0, ImageUrl: '', ProductStores: [] }));
                        self.insert = function (callback) {
                            var d = { value: p };
                            $.ajax({
                                url: "api/productsapi",
                                type: "POST",
                                data: d,
                                dataType: "json",
                                success: function (d) {
                                    self.d.ProductID = d;
                                    callback();
                                },
                                error: function (e) {
                                    alert("error posting");
                                }
                            });
                        }
                    } else {
                        self.data = ko.observableArray([]);
                        self.loadAll = function () {
                            $.ajax({
                                url: "api/productsapi",
                                dataType: "json",
                                data: "{}",
                                type: "GET",
                                success: function (result) {
                                    for (var i = 0; i < result.length; i++) {
                                        self.data.push(result[i]);
                                    }
                                },
                                error: function (err) {
                                    alert("error");
                                }
                            });
                        }
                    }
                };

                ko.applyBindings(new viewModel('l'));   //change to i for insert

            });
        </script>

        <div id="newprod" data-bind="visible: mode=='i'">
            <span data-bind="text: data().ShortName"></span>
        </div>

        <div id="listing" data-bind="visible: mode=='l'">
            <span data-bind="text: data().length"></span>
            <button data-bind="click: loadAll">Load</button>
        </div>

$(函数(){
//允许视图提交有关新产品的信息
//并获取产品数据
功能视图模型(模式){
var self=这个;
self.mode=模式;
如果(self.mode=='i'){
self.data=ko.observable(ko.mapping.fromJS({ProductID:0,ShortName:[新产品]',供应商代码:'',UnitsInBox:0,CostPerUnit:0,BoxSalePrice:0,ImageUrl:'',ProductStores:[]}));
self.insert=函数(回调){
var d={value:p};
$.ajax({
url:“api/productsapi”,
类型:“POST”,
数据:d,
数据类型:“json”,
成功:功能(d){
self.d.ProductID=d;
回调();
},
错误:函数(e){
警报(“错误发布”);
}
});
}
}否则{
self.data=ko.observearray([]);
self.loadAll=函数(){
$.ajax({
url:“api/productsapi”,
数据类型:“json”,
数据:“{}”,
键入:“获取”,
成功:功能(结果){
对于(变量i=0;i
但是让库中包含基于knockout的不同元素是非常不舒服的,不是吗?您只需像控制器一样使用viewModel,添加/删除希望knockout注意的内容。它们可以是自包含的实体,您只需在主视图模型中添加一个引用,这样就可以进行绑定。否则,您必须将每个模型绑定到不同的元素(而不是彼此的后代)。