我正在使用以下内容:
我想要实现的目标如下:
我猜它不起作用的原因,是因为模板在VM之前加载(它确实给我绑定错误)。
我的网站结构如下(不包括上述图书馆):
index.html
(持有模板容器)js/script.js
(持有主ViewModel)js/firstvm.js
(拥有第一个ViewModel)js/secondvm.js
(持有第二个ViewModel)tmpl/firstvm.html
(第一个虚拟机的模板)tmpl/secondvm.html
(第二个虚拟机的模板)Or simply download the source and view the problem.
最重要的部分:
的index.html
<button data-bind="click: loadFirstPage">Load first page + ViewModel</button>
<button data-bind="click: loadSecondPage">Load second page + ViewModel</button>
< hr />
<div data-bind="template: { name: function() { return currentTemplate(); }, data: currentData }"></div>
的script.js
function IndexViewModel() {
var vm = this;
this.currentTemplate = ko.observable();
this.currentData = ko.observable();
this.loadFirstPage = function() {
vm.currentTemplate("firstvm");
vm.currentData(new FirstViewModel());
};
this.loadSecondPage = function() {
vm.currentTemplate("secondvm");
vm.currentData(new SecondViewModel());
};
this.loadFirstPage();
};
ko.applyBindings(new IndexViewModel());
firstvm.html
<p data-bind="text: displayValue"></p>
secondvm.html
<p data-bind="text: displayValue2"></p>
firstvm.js
function FirstViewModel() {
this.displayValue = ko.observable("Text from firstvm.js");
};
secondvm.js
function SecondViewModel() {
this.displayValue2 = ko.observable("Text from secondvm.js");
};
我希望有人可以帮我解决这个问题。提前谢谢!
聚苯乙烯。忘记提及:当按下“第一页”按钮两次时,它似乎确实有效(可能是因为加载了正确的VM)。
答案 0 :(得分:7)
所以看起来问题是名称和数据需要同时更改,因此模板不会绑定到尚未存在的viewmodel。有几种方法可以解决这个问题。一个是加载模板并保留它们,但你可以继续重新加载它们:
模板绑定:
<div data-bind="template: {name: currentTemplate().name(),
data: currentTemplate().data() }"></div>
视图模型:
function TemplateViewModel(name, data) {
this.name = ko.observable(name);
this.data = ko.observable(data);
};
function IndexViewModel() {
var vm = this;
this.currentTemplate = ko.observable();
this.loadFirstPage = function() {
vm.currentTemplate(new TemplateViewModel("firstvm", new FirstViewModel()));
};
this.loadSecondPage = function() {
vm.currentTemplate(new TemplateViewModel("secondvm", new SecondViewModel()));
};
this.loadFirstPage();
};
ko.applyBindings(new IndexViewModel());
我测试了这个,它有效。你可能想稍微调整一下,但是你明白了。
答案 1 :(得分:1)
这已经回答了,但是我想分享我使用标准淘汰模板的解决方案。我创建了自定义绑定,并将包装模板渲染调用到setTimeout
以将渲染放到队列的末尾,并且它工作正常。这是代码:
ko.bindingHandlers.widget = {
'init': function(element, valueAccessor) {
return { 'controlsDescendantBindings': true };
},
'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var templateName = valueAccessor().widgetTemplate();
var dataValue = valueAccessor()
var innerBindingContext = bindingContext['createChildContext'](dataValue);
// This puts rendering of template to end of queue.
// This is to avoid binding errors while new template is assigned to old widget data
setTimeout(function(){
ko.renderTemplate(templateName, innerBindingContext, {}, element);
}, 0);
}
}
注意:自knockout 2.3 name
模板绑定also accept observable