问题描述
尝试按照 this tutorial 创建一个带刺激的无限滚动条。 这是我的观点:
<div data-controller="Feed" data-action="scroll@window->Feed#scroll" >
<div data-Feed-target="entries">
<%= render(partial: "Feed_posts")%>
</div>
<div data-Feed-target="pagination" hidden>
<%== pagy_nav(@pagy)%>
</div>
</div>
我的导轨控制器:
def Feed
@new_post = Post.new
@pagy,@posts = pagy(Post.where(user_id: current_user.all_following.pluck(:id)).or(Post.where(user_id: current_user.id)).order(created_at: :DESC),items: 5)
respond_to do |format|
format.html
format.json{
render json:{entries: render_to_string(partial: "Feed_posts",formats: [:html]),pagination: view_context.pagy_nav(@pagy)}
}
end
end
最后是我的 js 控制器:
export default class extends Controller {
static targets = ["entries","pagination"]
scroll(){
let next_page = this.paginationTarget.querySelector("a[rel ='next']")
if(next_page == null ){ return }
let url = next_page.href
var body = document.body,html = document.documentElement
var height = Math.max(body.scrollHeight,body.offsetHeight,html.clientHeight,html.scrollHeight,html.offsetHeight)
if(window.pageYOffset >= height - window.innerHeight - 100){
console.log("loading")
this.loadMore(url)
}
}
loadMore(url){
Rails.ajax({
type: 'Get',url: url,dataType: 'json',success: (data) => {
console.log(data)
this.entriesTarget.insertAdjacentHTML('beforeend',data.entries);
this.paginationTarget.innerHTML = data.pagination
}
})
}
}`
负责确定页面底部是否被点击的代码每次运行的次数不同,并且向视图中添加了过多的结果。
我怎样才能让它运行一次,或者让它检查是否添加了 html,之前是否添加过......或者这可能不是一个好主意。
解决方法
此技术称为 Throttle
:保证函数定期执行,每 X 毫秒仅执行一次。
查看CSS-TRICKS - Debouncing and Throttling Explained Through Examples的详细信息
将油门与刺激一起使用的简单方法是使用 lodash 中的 _throttle
函数
_.throttle(func,[wait=0],[options={}])
查看 Debounce and throttle in Stimulus、_.throttle inside a controller 上的用例
,您正在使用的教程的来源 GoRails 有一个名为 Throttling Infinite Scroll Events in Javascript 的后续剧集。如果您不是该网站的 Pro 会员,您将无法观看该视频,但有一个指向 the source code on GitHub 的链接,可免费获得。它提供了以下更新的 infinite_scroll_container.js
:
import { Controller } from "stimulus"
export default class extends Controller {
static targets = ["entries","pagination"]
scroll() {
let next_page = this.paginationTarget.querySelector("a[rel='next']")
if (next_page == null) { return }
let url = next_page.href
var body = document.body,html = document.documentElement
var height = Math.max(body.scrollHeight,body.offsetHeight,html.clientHeight,html.scrollHeight,html.offsetHeight)
if (window.pageYOffset >= height - window.innerHeight) {
this.loadMore(url)
}
}
loadMore(url) {
if (this.loading) { return }
this.loading = true
Rails.ajax({
type: 'GET',url: url,dataType: 'json',success: (data) => {
this.entriesTarget.insertAdjacentHTML('beforeend',data.entries)
this.paginationTarget.innerHTML = data.pagination
this.loading = false
}
})
}
}