动态添加列表项后如何滚动至最后一项?
解决动态添加列表项后无法自动滚动到底部的问题
我来帮你排查下这个问题~你当前的滚动动画不生效,主要是因为动画执行时机不对,再加上选择器有小错误,导致DOM更新和滚动动作不同步。
问题原因分析
- 你使用了
delay(1000).queue()来异步添加列表项,但滚动动画animate是在each循环里直接执行的——此时对应的列表项还没被添加到DOM中,scrollHeight还是旧的数值,自然无法滚动到正确位置。 - 选择器里多余的转义符:比如
$("\.scontrino")应该写成$(".scontrino"),否则jQuery无法正确选中目标元素。
修正后的完整代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" /> <div class="row h-100"> <div class="col-5"> <div class="scontrino"> <h4>Il tuo carrello</h4> <hr /> <ul class="list-group"></ul> <hr /> <div class="alert alert-dark totale" role="alert"> Totale <span class="price float-right">€0.00</span> </div> <div class="alert alert-success" role="alert"> Fidelity <span class="float-right">001230013212</span> </div> </div> </div> <div class="col-7 p-0 bg-light"> </div> </div>
CSS
html, body { font-family: 'PTSans', Fallback, sans-serif; background: #00383e; height: 100%; } .scontrino { margin-bottom: 1rem; position: relative; background: #f8f7f5; height: 95%; padding: 1rem; font-size: 1.4rem; } .scontrino:after { content: " "; display: block; height: 24px; position: absolute; left: 0; right: 0; } .scontrino:after { bottom: -14px; background: linear-gradient(135deg, #fcfcfb 25%, transparent 25%), linear-gradient(225deg, #fcfcfb 25%, transparent 25%); background-size: 24px 24px; background-color: #00383e; } .list-group { max-height: 350px; overflow: scroll; -webkit-overflow-scrolling: touch; } .list-group-item { border-color: #fff; border-radius: 0.25rem; margin-bottom: 1rem; border-top-width: 1px !important; animation-duration: 0.5s; animation-name: slidein; } @keyframes slidein { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
JavaScript
var prodotti = [{ desc: "Prosciutto", qta: 2, prezzo: 2 }, { desc: "Carne", qta: 1, prezzo: 15 }, { desc: "Pomodori", qta: 6, prezzo: 3 }, { desc: "Pandoro", qta: 5, prezzo: 22 }, { desc: "Yougurt", qta: 3, prezzo: 5 }, { desc: "Pomodori", qta: 6, prezzo: 3 }, { desc: "Pandoro", qta: 5, prezzo: 22 }, { desc: "Yougurt", qta: 3, prezzo: 5 }, { desc: "Pomodori", qta: 6, prezzo: 3 }, { desc: "Pandoro", qta: 5, prezzo: 22 }, { desc: "Yougurt", qta: 3, prezzo: 5 } ]; var height = $(".scontrino").height(); $(".list-group").css("max-height", height - 250); // setting the height to list-group var list = $(".list-group"); $.each(prodotti, function(key, prodotto) { $(".btn-finish").removeAttr("disabled"); list.delay(1000).queue(function(next) { $(this).append( $("<li>", { class: "list-group-item d-flex justify-content-between", }).append( $("<span>", { class: "desc" }).text(prodotto.desc), $("<span>", { class: "qta" }).text(prodotto.qta), $("<span>", { class: "prezzo" }).text(prodotto.prezzo) ) ); // 确保DOM更新后再执行滚动动画 $(this).animate({ scrollTop: $(this).prop("scrollHeight") }, 500); next(); }); });
关键修改点
- 修正选择器:移除了选择器中多余的转义符(比如
$("\.scontrino")→$(".scontrino")),确保jQuery能正确选中元素。 - 同步动画时机:将滚动动画放到
queue的回调函数内部,这样每次添加完列表项后,DOM已经更新,此时获取的scrollHeight是最新的,滚动动画就能准确滚动到底部。 - 移除无效动画调用:删掉了
each循环中独立的animate调用,避免在DOM未更新时执行无效的滚动操作。
如果你希望所有列表项添加完成后只滚动一次,可以把滚动逻辑放到队列的promise().done()回调中,这样所有异步添加操作完成后再执行一次滚动:
// 替换each循环内的queue部分 list.delay(1000).queue(function(next) { $(this).append(/* 列表项代码 */); next(); }).promise().done(function() { list.animate({ scrollTop: list.prop("scrollHeight") }, 500); });
内容的提问来源于stack exchange,提问作者NiceToMytyuk
相关产品推荐
相关产品推荐

