同一视图模板中实现Turbo Frame懒加载并解决自引用错误
解决Turbo Frame懒加载自引用报错问题
我在长网页视图模板(比如long_page.html.erb)底部有重型计算内容,拖慢了页面整体加载速度。因为用户不一定会滚动到底部,想通过懒加载的<turbo-frame>实现仅当用户滚动至底部时才加载该重型内容,而且不想新建额外的控制器动作和视图模板。
尝试添加以下代码后,控制台出现报错:
# long_page.html.erb <turbo-frame id="heavy_content_inside" loading="lazy" src="path/to/long_page"> <% # 这里是拖慢加载的重型计算内容 %> </turbo-frame>
报错信息:
Error: Matching element has a source URL which references itself
问题原因
报错是因为Turbo Frame的src属性指向了当前页面的URL,导致循环引用请求,Turbo会阻止这种无效的自引用行为。
解决方案
不需要设置src属性,而是通过控制器参数+条件渲染结合Turbo的惰性加载机制实现需求,全程复用原有的控制器动作和视图模板:
- 修改控制器动作,添加参数判断是否需要加载重型内容:
# 对应long_page的控制器动作 def long_page # 通过URL参数判断是否要渲染重型内容 @load_heavy = params[:load_heavy].present? end
- 修改视图模板,调整Turbo Frame的写法:
<turbo-frame id="heavy_content_inside" loading="lazy" data-turbo-action="advance"> <% if @load_heavy %> <%# 这里放原来的重型计算内容,也可以抽成partial %> <%= render 'heavy_content' %> <% else %> <!-- 初始加载时显示占位符,不渲染重型内容 --> <div class="text-center py-8"> <span class="loading-spinner">加载中...</span> </div> <!-- 告诉Turbo懒加载时要请求的带参数地址 --> <%= tag.meta name="turbo-reload-url", content: long_page_path(load_heavy: true) %> <% end %> </turbo-frame>
原理说明
- 页面初始加载时,
@load_heavy为false,Turbo Frame内只显示占位符,重型内容不会被计算和渲染,页面加载速度不受影响。 - 当用户滚动到Turbo Frame的位置时,Turbo会自动读取
turbo-reload-url中的地址发起请求,带上load_heavy=true参数。 - 控制器接收到参数后,
@load_heavy变为true,视图渲染重型内容,Turbo会自动用新内容替换Frame内的占位符。 data-turbo-action="advance"可以避免浏览器历史记录中重复添加相同页面的记录,可根据需求选择是否保留。
内容的提问来源于stack exchange,提问作者Backo
相关产品推荐
相关产品推荐

