Javascript 在主干应用程序中的渲染函数上使用addClass()和CSS转换无法正常工作

Javascript 在主干应用程序中的渲染函数上使用addClass()和CSS转换无法正常工作,javascript,jquery,css,backbone.js,css-transitions,Javascript,Jquery,Css,Backbone.js,Css Transitions,在我的backbone.js应用程序中,我试图在添加视图元素后淡入该元素。但是它不起作用 现场示例如下: 但是,如果我添加一个小的setTimeout函数,它就可以工作了 var itemRender = view.render().el; $('#items-list').append(itemRender); setTimeout(function(){ $(itemRender).addClass('show'); },10); 使用

在我的backbone.js应用程序中,我试图在添加视图元素后淡入该元素。但是它不起作用

现场示例如下:

但是,如果我添加一个小的setTimeout函数,它就可以工作了

    var itemRender = view.render().el;

    $('#items-list').append(itemRender);

    setTimeout(function(){
        $(itemRender).addClass('show'); 
    },10);
使用fadeIn()也可以,但我更喜欢使用直接的CSS进行转换,因为它更有效,并且不喜欢使用任何setTimeout“hacks”来强制它工作。是否有可用于追加的回调?或者有什么建议?完整代码如下:

itemRender: function (item) {
    var view = new app.ItemView({ model: item }),
        itemName = item.get('name'),
        itemRender = view.render().el;

    $('#items-list').append(itemRender);
    $(itemRender).addClass('show');

    app.itemExists(itemName);
}
CSS/LESS:

#items-list li {
    padding: 0 10px;
    margin: 0 10px 10px;
    border: 1px solid @black;
    .border-radius(10px);
    position: relative;
    .opacity(0);
    .transition(opacity)
}

#items-list li.show {.opacity(1)}
您提到的这种“黑客”技术(或其变体)对于web开发偶尔是必要的,这仅仅是由于浏览器呈现页面的性质

(注意:这都是出于记忆,所以尽管整体想法是正确的,但请对任何细节稍加保留。)

假设您执行以下操作:

$('#someElement').css('backgroundColor', 'red');
$('#someElement').css('backgroundColor', 'blue');
您可能希望看到
#someElement
的背景色短暂闪烁红色,然后向右转为蓝色?但是,这不会发生,因为浏览器试图通过仅在JS执行结束时渲染最终状态来优化渲染性能。因此,红色背景永远不会出现在页面上;你所能看到的只有蓝色

与此类似,以下各项之间的区别:

  • 附加
  • 定级
  • 以及:

  • 附加
  • 等待1毫秒,等待JS执行完成
  • 定级
  • 后者允许元素进入页面并在执行JS后更改其样式,而前者只在元素显示之前应用样式更改

    因此,在一般情况下,当您需要处理这些问题时,应该避免使用
    window.setTimeout
    。。。浏览器渲染的复杂性,这真的是唯一的出路。我个人喜欢使用下划线库的defer函数:

    var itemRender = view.render().el;
    
    $('#items-list').append(itemRender);
    
    _(function(){
        $(itemRender).addClass('show'); 
    }).defer();
    

    这是同样糟糕的事情,但因为它封装在一个库函数中,所以对我来说感觉不那么脏:-)(如果“后期渲染”逻辑超过一两行,我可以将其分解到主干视图方法中并执行
    (this.postRender).defer()
    在我的
    渲染
    方法中)。

    你可以使用CSS动画

    @keyframes show {
      0%   { opacity: 0; }
      100% { opacity: 1; }
    }
    
    #items-list li {
        padding: 0 10px;
        margin: 0 10px 10px;
        border: 1px solid @black;
        .border-radius(10px);
        position: relative;
    }
    #items-list li.show {
        animation: show 1s;
    }
    

    这让我有一段时间受挫了,谢谢你解释得这么好。
    @keyframes show {
      0%   { opacity: 0; }
      100% { opacity: 1; }
    }
    
    #items-list li {
        padding: 0 10px;
        margin: 0 10px 10px;
        border: 1px solid @black;
        .border-radius(10px);
        position: relative;
    }
    #items-list li.show {
        animation: show 1s;
    }