Knockout.js I';我对淘汰赛有意见';在移除回调和CSS转换之前

Knockout.js I';我对淘汰赛有意见';在移除回调和CSS转换之前,knockout.js,Knockout.js,我正在使用foreach绑定和beforeRemove回调来设置删除列表项的动画。当我移除之前移除的项目上方的项目时效果良好,但当我尝试移除之前移除的项目下方的项目时,转换无法正常工作 下面是一个JSFIDLE来说明我的问题: HTML JS 函数vm(){ “严格使用”; var me=这个; me.people=ko.array([ {“姓名”:“Irma Olsen”}, {“name”:“Winifred Cabrera”}, // ... {“姓名”:“卢修斯·霍华德”}, {“姓名

我正在使用foreach绑定和beforeRemove回调来设置删除列表项的动画。当我移除之前移除的项目上方的项目时效果良好,但当我尝试移除之前移除的项目下方的项目时,转换无法正常工作

下面是一个JSFIDLE来说明我的问题:

HTML

JS

函数vm(){
“严格使用”;
var me=这个;
me.people=ko.array([
{“姓名”:“Irma Olsen”},
{“name”:“Winifred Cabrera”},
// ...
{“姓名”:“卢修斯·霍华德”},
{“姓名”:“赫达桑塔纳”}
]);
me.removePerson=函数(person){
我。人。移除(人);
};
me.animateOut=函数animateOut(节点、i、人){
//确保它不是文本节点
if(node.nodeType==node.ELEMENT\u node){
node.classList.add(“remove”);
}
}
}
应用绑定(新vm());

这是一个奇怪的问题,但我认为这与疯狂的浏览器渲染逻辑有关。你需要强制重画一张没有发生的照片。我们曾经:

<div class="person remove">
<div class="person">

然后我们去

<div class=person>
<div class=person>

同一个div不再有
remove
类——当我们添加
remove
类时,Knockout会删除数据,但是浏览器不知道更新这个div,因此它不会执行转换,这意味着
transitionEnd
不会触发,div也不会被删除

那么我们如何强制重画呢?(一个有效的表达)


我相信有人可以更雄辩地解释这是如何工作的,以及为什么需要这样做,但至少它应该可以解决您眼前的问题。

您的转换在
删除发生后结束,因此可能会弄乱渲染

您可以通过通知
人员
集合转换已结束来修复此问题

me.animateOut = function animateOut(node, i, person) {
    // Make sure it's not a text node
    if (node.nodeType == Node.ELEMENT_NODE) {
        node.addEventListener("transitionend", function () {
            this.parentElement.removeChild(this);
            me.people.notifySubscribers(); // Add this line here
        });
        node.classList.add("remove");
    }
}

请注意,如果您有手动订阅,他们将收到通知回调的
undefined
参数的通知,因此您应该做好准备。

beforeRemove
事件的中:

beforeRemove
-在删除数组项时调用,但 在删除相应的DOM节点之前。如果指定 在删除回调之前,那么您有责任删除回调 DOM节点。

beforeRemove
中,仅当DOM节点不是文本节点时才删除它们,但需要删除所有节点

因此,您需要使用
node.parentElement.removeChild(node)添加一个
else
大小写


演示。

疯狂的调用
node.offsetHeight
修复了这个问题,我也不知道为什么这个黑客在这种情况下有效。谢谢,解决了这个问题。谢谢。可能最好也删除文本节点,但重画会解决问题。我认为正确的解决方案是删除文本节点,因为在这种情况下,knockout会正确处理渲染,而您不会强行重画…它确实有帮助,但是,在上一次转换仍在进行时删除项目时,仍然会出现此问题。强制重画是可行的。
<div class=person>
<div class=person>
me.animateOut = function animateOut(node, i, person) {
    // Make sure it's not a text node
    if (node.nodeType == Node.ELEMENT_NODE) {
        node.addEventListener("transitionend", function () {
            this.parentElement.removeChild(this);
            me.people.notifySubscribers(); // Add this line here
        });
        node.classList.add("remove");
    }
}
me.animateOut = function animateOut(node, i, person) {
    // Make sure it's not a text node
    if (node.nodeType == Node.ELEMENT_NODE) {
        node.addEventListener("transitionend", function () {
            this.parentElement.removeChild(this);
        });
        node.classList.add("remove");
    }
    else{
        node.parentElement.removeChild(node);
    }
}