淘汰:交换使用子ViewModel的HTML

时间:2014-02-08 07:04:07

标签: knockout.js

我有一个应用程序,可以在加载时构建一个小页面,向用户显示导航选项。当用户选择导航选项时,页面会创建一个表示所选导航选项的ViewModel的对象,然后从服务器获取相应的HTML并将其放在div中。

我的期望是我可以获取HTML,使用Knockout HTML绑定将其放入div(包含在带有预选ID的容器div中),然后将容器div绑定到ViewModel。

但是,当我尝试这样做时,我会收到错误。这看起来非常符合Knockout应该做的事情,所以我对我做错了什么感到有些困惑。任何帮助将不胜感激。

我创建了一个小提琴来封装问题(点击链接什么都不做):

http://jsfiddle.net/Tgh44

这是HTML:

<body>
    <div id="container">
        <div id="menu">
            <ul data-bind="foreach: modules">
                <li><a href="#" data-bind="click: $root.goTo.bind($data), text: $data"></a></li>
            </ul>
        </div>
        <div id="body" data-bind="html: curBody">

        </div>
    </div>
</body>

JavaScript:

function GlobalVM() {
    var self = this;

    self.curVM = ko.observable();
    self.test = ko.observable('test');

    self.curBody = ko.observable('body');    
    self.modules = ko.observableArray();

    self.goTo = function(module) {
        if (module == 'Test1') {
            self.curVM(new SubVM1());

            self.curBody('<div id=\'realbody\' data-bind=\'text: curVM().test1\'></div>');
            ko.applyBindings(self, document.getElementById('realbody'));
        }

        if (module == 'Test2') {
            self.curVM(new SubVM2());

            self.curBody('<div id=\'realbody\' data-bind=\'text: curVM().test2\'></div>');
            ko.applyBindings(self, document.getElementById('realbody'));
        }
    };

    self.initialize = function() {
        self.modules.push('Test1');
        self.modules.push('Test2');
    };
}

function SubVM1() {
    var self = this;

    var test1 = ko.observable('test1');
}

function SubVM2() {
    var self = this;

    var test2 = ko.observable('test2');
}

var vm = new GlobalVM();
vm.initialize();
ko.applyBindings(vm);

1 个答案:

答案 0 :(得分:0)

使用模板可能是最好的方法。这是一个updated fiddle来证明这一点。

我添加了一个跟踪当前“页面”

的observable

self.currentPage = ko.observable('Home');

然后在您的goTo方法中,我将其更改为

self.goTo = function(module) {
    self.currentPage(module);
};

并将模板添加到html。

修改

我刚看到您对原帖的评论。是的,您可以动态加载模板。您可以通过将该模板动态添加到DOM来加载模板。例如:

$.get(templateurl, function(data){
    $('body').append('<div style="display:none">' + data + '<\/div>');
});

如果您有许多模板(或任何模板),如果您将模板保存在单独的文件中 - 与主视图的HTML分开,则更简洁,更容易使用。然后,您可以通过ajax将它们全部加载到视图中。但是,如果将绑定应用于整个页面,则在调用ko.applyBindings之后加载模板将不起作用。有些选项会在单个DOM元素上调用ko.applyBindings或使用ko.renderTemplate - 请参阅this SO post on lazy loading KO templates以获取一些好主意。