Knockoutでノードをクリアした後でもバインディングを適用できません。私は、ユーザーの操作(ボタンをクリックするなど)に基づいてコンポーネントを動的に使用しようとしています。Knockout.jsのノードをクリアした後でバインディングを再適用する方法は?
私はそれらを作成し、削除し、コンポーネントを処理するための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を使用していますので、私はのためのJavaScriptファイルを含むオブジェクトを持つコンポーネントを宣言ViewModelにテンプレート:
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]);
これでサンプルform.js内部のViewModelファイル:
UIComponent.render(QuoteForm, $('quote-form')[0]);
setTimeout(function() {
UIComponent.remove(QuoteForm, $('quote-form')[0]);
}, 2000);
setTimeout(function() {
UIComponent.render(QuoteForm, $('quote-form')[0]);
}, 4000);
最初:
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
機能を使用していますテストするにはsetTimeout
が実行され、SampleFormModel disposed
というメッセージがコンソールに記録されていますが、2番目のメッセージがsetTimeout
で実行されると、ノックアウトからエラーが表示されます。
Uncaught Error: You cannot apply bindings multiple times to the same element.
ノックアウトがコンポーネントを廃棄しても、同じノードにバインディングを再度適用することはできません。
引数なしで 'ko.applyBindings();'を呼び出すので、DOMツリー全体に適用されます。特定のノードのみをクリーニングしています。 ko.componentsがあなたのために世話をしてくれることを、あなたが手でやっていると確信しています。 'cleanNode'をまったく使う必要はありません。 –
WOW!それはトリックでした!どうもありがとうございました! –