Javascript 如何在KO外部模板引擎中使用本机敲除模板

Javascript 如何在KO外部模板引擎中使用本机敲除模板,javascript,jquery,knockout.js,knockout-templating,Javascript,Jquery,Knockout.js,Knockout Templating,我正在使用KO外部模板引擎将我的单页webapp分解为多个文件,但我正在加载的模板只包含KO标记 尽管对这个主题进行了广泛的研究,但我还是不知道如何将KO绑定可靠地应用于正在加载的模板 关键是: 模板定义的DOM元素最初不存在 我的模板绑定是动态的,所以我不知道KO在对整个文档应用绑定时会请求模板 我不想使模板加载同步 pb变得更加棘手,因为infuser可能正在进行一些模板缓存,这导致KO抱怨我应用了两次绑定 这是我的代码,它至少有两个问题: 当我调用applyBindings时,不能保

我正在使用KO外部模板引擎将我的单页webapp分解为多个文件,但我正在加载的模板只包含KO标记

尽管对这个主题进行了广泛的研究,但我还是不知道如何将KO绑定可靠地应用于正在加载的模板

关键是:

  • 模板定义的DOM元素最初不存在
  • 我的模板绑定是动态的,所以我不知道KO在对整个文档应用绑定时会请求模板
  • 我不想使模板加载同步
  • pb变得更加棘手,因为infuser可能正在进行一些模板缓存,这导致KO抱怨我应用了两次绑定
这是我的代码,它至少有两个问题:

  • 当我调用applyBindings时,不能保证模板已经完成加载
  • KO抱怨我在来回导航时试图重新应用绑定
在外部模板节点被添加到DOM时,有没有建议使用一种干净、可靠的方法将绑定应用于外部模板节点一次或仅一次

  • 在index.html中:


这不是一个关于如何使用模板的解决方案,但这是我如何使用将文件拆分成的

假设您有这样一个页面:

<div data-bind="with: block1">
    <input data-bind="value: yourFirstInput" />
    <!-- more markeup -->
</div>
<div data-bind="with: block2">
    <select data-bind="options: dropDownlist2options"></select>
    <!-- more markeup -->
</div>
这样,您可以在整个页面上应用绑定。带绑定的
将处理空/未定义对象的检查,并仅在对象实例化时显示块

然后,当您想显示
块1
时,可以执行类似操作:

vm.block1({ yourFirstInput: ko.observable('aa')});
实际上,我是通过映射插件实现的,这只是一个例子


(注意设置超时后block1是如何显示的)

如果我给了你一个要点,那么你可以这样做

使用get和assign-to-script标记将模板加载到js中的一个基本文件中,如下所示

var script   = document.createElement("script");
               script.id  = "YourTemplateName";
               script.type  = "text/html";
               script.text  = result.Value; //template data
               document.body.appendChild(script);
并在索引/基本html文件中指定模板

<div id="OtherTemplateDiv" data-bind="template: { name: 'YourTemplateName' }">
            </div>

我为KO制作了一个模板引擎

它需要一个启用Owin的web服务器,一旦配置好,它就知道名为
FooViewModel
的视图模型应该连接到名为
FooView

使用nuget安装(适用于ASP.NET)

它的设计也很容易在水疗中心使用

演示

我想出了一些使用afterRender回调的方法。。。虽然有点凌乱,但我们欢迎改进

由于某种原因,afterRender回调被调用了两次,第二次调用的对象为空,因此需要对hasOwnProperty('nodeType')进行测试

isBound()检查绑定是否已应用于元素-在应用绑定失败后,尝试向元素添加自定义标记CSS(“ko-applicated”)类

不确定是否确实需要复制koElements数组,但如果不这样做,我的循环中就有未定义的元素[I],因此模板加载程序可能会在afterRender运行时异步更新数组

<div id="templateDiv" data-bind="template: { name: currentView(), afterRender: applyTemplateBindings }"></div>

self.applyTemplateBindings = function(koElements) {
            var elements = koElements.slice();
            for (var i = 0, len = elements.length; i < len; i++) {
                var element = elements[i];
                if (element.hasOwnProperty('nodeType') && ! $(element).hasClass('infuser-loading') &&
                    ! isBound(element)) {
                    ko.applyBindings(self, element);
                }
            }
        };

        var isBound = function(node) {
            return !!ko.dataFor(node);
        };

self.applyTemplateBindings=函数(元素){
var elements=koElements.slice();
for(var i=0,len=elements.length;i
Hmmm,问题是我可能有50多个外部模板,所以我不想在调用applyBindings()之前加载所有模板。因为所有DOM节点(主文档和所有模板)都是在调用applyBindings之前创建的,所以fiddle可以工作,不是吗?实际上,重要的是在调用相关DOM元素上的applyBindings之前定义块。您可以在之后加载标记,但是您必须对其调用applyBindings(ko.applyBindings(vm,domElement)),我已经解决了这一部分。问题在于在初次调用applyBindings后加载的外部模板(比如在通过应用程序导航15分钟后,用户突然导航到加载新模板的视图)。请尝试类似这样的操作:ko.applyBindings(objectLateLoaded,$(“#DivIdInWhichTemplateAdded”)[0];
var script   = document.createElement("script");
               script.id  = "YourTemplateName";
               script.type  = "text/html";
               script.text  = result.Value; //template data
               document.body.appendChild(script);
<div id="OtherTemplateDiv" data-bind="template: { name: 'YourTemplateName' }">
            </div>
Install-Package Knockout.Bootstrap.TemplateStore.SystemWeb
<div id="templateDiv" data-bind="template: { name: currentView(), afterRender: applyTemplateBindings }"></div>

self.applyTemplateBindings = function(koElements) {
            var elements = koElements.slice();
            for (var i = 0, len = elements.length; i < len; i++) {
                var element = elements[i];
                if (element.hasOwnProperty('nodeType') && ! $(element).hasClass('infuser-loading') &&
                    ! isBound(element)) {
                    ko.applyBindings(self, element);
                }
            }
        };

        var isBound = function(node) {
            return !!ko.dataFor(node);
        };