即使在Knockout上清除节点后,我也无法应用绑定。我正在尝试根据用户操作动态使用组件(单击按钮等)。
我创建了一个UIComponent类来处理组件,创建和删除它们:
(function (window) {
define(['knockout'], function (ko) {
/**
* Custom component to the given DOM node
* @type {{render: UIComponent.render}}
*/
var UIComponent = (function () {
return {
/**
* Render a component
* @param {object} component
* @param {object} element
*/
render: function (component, element, childComponents) {
var tagName = element.tagName && element.tagName.toLowerCase();
if (ko.components.isRegistered(tagName)) {
ko.components.unregister(tagName);
}
if (undefined !== childComponents) {
childComponents.forEach(function (child) {
if (ko.components.isRegistered(child.tagName)) {
ko.components.unregister(child.tagName);
}
ko.components.register(child.tagName, child.component);
});
}
ko.components.register(tagName, component);
ko.applyBindings();
},
/**
* Removes a component
* @param {object} component
* @param {object} element
*/
remove: function (component, element) {
ko.components.unregister(component.name);
ko.cleanNode(element);
// Remove any child elements from node
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
};
})();
window.UIComponent = UIComponent;
return UIComponent;
});
})(window);
我正在使用RequireJS动态加载组件的文件,所以我声明了一个组件,其中包含一个包含viewModel javascript文件的对象和一个模板:
var QuoteForm = {
viewModel: {
require: '/scripts/components/sample-form.js'
},
template: {
require: 'text!/templates/forms/available-products-quote-form.html'
}
};
我在UIComponent类上使用这个组件对象,如下所示:
UIComponent.render(QuoteForm, $('quote-form')[0]);
这是 sample-form.js 文件中的viewModel:
define(['knockout'], function (ko) {
var SampleFormModel = function (params) {
};
SampleFormModel.prototype = {
/**
* Dispose any resources used on component
*/
dispose: function () {
console.log('SampleFormModel disposed');
}
};
return SampleFormModel;
});
为了测试,我使用简单的setTimeout
函数来模拟用户操作:
UIComponent.render(QuoteForm, $('quote-form')[0]);
setTimeout(function () {
UIComponent.remove(QuoteForm, $('quote-form')[0]);
}, 2000);
setTimeout(function () {
UIComponent.render(QuoteForm, $('quote-form')[0]);
}, 4000);
当第一个setTimeout
执行时,我在控制台上记录了SampleFormModel disposed
消息,但是当第二个setTimeout
执行时,我从Knockout收到错误:
Uncaught Error: You cannot apply bindings multiple times to the same element.
即使Knockout处理组件,我也无法再次在同一节点上应用绑定。
答案 0 :(得分:3)
就像Roy J所说,我正在将绑定应用于整个DOM。我只是对exports.handler = function (event, context) {
try {
console.log("event.session: " + event.session);
类进行了一些更改,只是为了将组件注册到特定元素:
UIComponent
现在它的工作就像一个魅力!
答案 1 :(得分:1)
您需要在对同一元素应用绑定之前清理元素,因此,您可以使用
清理元素ko.cleanNode(element)
此函数将从要重新应用绑定的节点上删除所有绑定。
答案 2 :(得分:0)
我对Knockout Components还不是很熟悉,但我一直在看文档。
这里有一个小问题:
如果您希望组件的所有实例共享同一个viewmodel对象实例(通常不需要)...有必要指定viewModel:{instance:object},而不仅仅是viewModel:object。
查看代码,您实际上拥有HTML组件的多个实例(通过呈现两次),但您正在重用viewmodel。你试过这个:
var QuoteForm = {
viewModel: {
instance: { require: '/scripts/components/sample-form.js' }
},
template: {
require: 'text!/templates/forms/available-products-quote-form.html'
}
};