無論何時您需要更改DOM,您都應該嘗試通過敲除數據綁定來完成此操作。大部分可以通過敲除的默認綁定來完成;有些東西需要自定義綁定。
對於第一部分:添加開放類應通過css
綁定發生:
data-bind="css: { 'classname' : state }"
在您的視圖模型,添加一個cartIsOpen
觀察到的和openCart
方法。
self.isOpen(true);
和淘汰賽:
data-bind="css: {'open': isOpen }"
jQuery的線可以被替換爲:現在
self.isOpen = ko.observable(false);
,您可以通過添加這個數據綁定到其容器元素在視覺上打開你的車會照顧css。
現在,對於(更復雜)第二部分:
聽在容器外的事件是不是淘汰賽的常規click
或event
結合能做到。所以你必須寫一個自定義綁定。
聽事件外某個元素可能相當棘手;我建議尋找堆棧溢出的一些一般建議。你需要非常小心event.stopPropagation()
它的工作。
在下面的例子中,我編寫了一個clickOutside
綁定的粗略示例。請注意,這不是一個「完成」的例子:
- 任何點擊您的頁面將觸發
closeOnClickOutside
方法;你需要找到一種方法來附加偵聽器時isOpen
設置爲true
,並處置一次它被設置爲false
。
- 無論何時您想打開菜單,您都需要明確地停止點擊事件到達文檔。 (在示例中爲
cancelBubble
)。否則,菜單立即打開和關閉。
var elementContainsChild = function(parent, child) {
// http://stackoverflow.com/a/2234986/3297291
var node = child.parentNode;
while (node !== null) {
if (node === parent) {
return true;
}
node = node.parentNode;
}
return false;
};
ko.bindingHandlers.clickOutside = {
init: function(element, valueAccessor) {
var cb = valueAccessor();
var closeOnClickOutside = function(e) {
if (e.target !== element &&
!elementContainsChild(element, e.target)) {
cb();
}
};
document.addEventListener("click", closeOnClickOutside);
}
}
var vm = {
isOpen: ko.observable(false)
};
ko.applyBindings(vm);
html, body { height: 100%; background: grey; }
.menu { background: yellow; display: none; }
.menu.open { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<button data-bind="click: isOpen.bind(null, true), clickBubble: false">open menu</button>
<div class="menu" data-bind="css: {'open' : isOpen }, clickOutside: isOpen.bind(null, false)">
<ul>
<li>Menu item</li>
<li>Menu item</li>
<li>Menu item</li>
<li>Menu item</li>
</ul>
</div>
我意識到,哇。我開始討論這種錯誤。我會嘗試你所說的。非常有幫助 – erics15
還有一個問題 - 我將如何鏈接到已經看起來像這樣的按鈕。 ?謝謝! – erics15
如果'addProductToCart'應該打開菜單('self.isOpen(true)'),則還需要將'clickBubble:false'數據綁定添加到按鈕。如果你不這樣做,按鈕上的點擊事件將(1)打開菜單,(2)一直向上冒泡,記錄它(3)再次關閉菜單的位置(假設你還沒有改變自定義綁定)。 – user3297291