求助:tanthammar/laravel-window-size断点内容需刷新才显示
问题描述
使用tanthammar/laravel-window-size包时,整体功能正常,但存在以下问题:
- 首次打开页面时,对应断点的内容无法正确显示
- 桌面端调整窗口大小后,断点内的内容不会自动切换,必须刷新页面才能生效
相关代码如下:
<head> <x-window-size::save-to-session /> </head> <body> @windowWidthGreaterThan(768) <!-- 仅在md及以上屏幕可见,sm及以下隐藏 --> <div class="article-body d-none d-md-block"> {!! $article->body !!} </div> @else <!-- 仅在xs、sm屏幕可见,md及以上隐藏 --> <div class="article-body d-md-none"> {!! $article->bodyX !!} </div> @endif </body>
解决方案
这个包的核心是后端通过Session存储窗口尺寸,再基于该值渲染内容。但窗口调整是前端事件,后端无法实时感知,因此需要通过前端触发Session更新或内容切换。
方法1:监听窗口resize,AJAX更新Session并局部刷新
- 添加防抖处理的JavaScript监听事件:
// 防抖函数,避免频繁触发请求 function debounce(func, wait) { let timeout; return function() { clearTimeout(timeout); timeout = setTimeout(func, wait); }; } // 监听窗口resize window.addEventListener('resize', debounce(function() { const currentWidth = window.innerWidth; // 发送请求更新Session中的窗口尺寸 fetch('/update-window-size', { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, 'Content-Type': 'application/json' }, body: JSON.stringify({ width: currentWidth }) }) .then(res => res.json()) .then(() => { // 重新加载文章内容片段 fetch(`/article-body/{{ $article->id }}`) .then(res => res.text()) .then(html => { document.querySelector('.article-body').parentElement.innerHTML = html; }); }); }, 250));
- 后端添加路由与控制器方法:
- 路由(
routes/web.php):
use App\Http\Controllers\ArticleController; Route::post('/update-window-size', [ArticleController::class, 'updateWindowSize']); Route::get('/article-body/{article}', [ArticleController::class, 'getArticleBody']);
- 控制器方法:
namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Models\Article; use Tanthammar\LaravelWindowSize\WindowSize; class ArticleController extends Controller { public function updateWindowSize(Request $request) { $request->validate(['width' => 'required|integer']); // 更新Session中的窗口尺寸 WindowSize::saveToSession($request->width, window.innerHeight); return response()->json(['success' => true]); } public function getArticleBody(Article $article) { // 返回渲染后的内容片段 return view('partials.article-body', compact('article')); } }
- 创建内容片段视图
resources/views/partials/article-body.blade.php:
@windowWidthGreaterThan(768) <div class="article-body d-none d-md-block"> {!! $article->body !!} </div> @else <div class="article-body d-md-none"> {!! $article->bodyX !!} </div> @endif
方法2:纯前端切换(适合静态内容)
如果文章内容无需后端动态处理,可直接用JS控制显示隐藏,绕开Session依赖:
<head> <x-window-size::save-to-session /> </head> <body> <!-- 同时渲染两个内容块 --> <div class="article-body d-none d-md-block desktop-content"> {!! $article->body !!} </div> <div class="article-body d-md-none mobile-content"> {!! $article->bodyX !!} </div> <script> function toggleContent() { const isDesktop = window.innerWidth > 768; const desktopEl = document.querySelector('.desktop-content'); const mobileEl = document.querySelector('.mobile-content'); desktopEl.classList.toggle('d-none', !isDesktop); desktopEl.classList.toggle('d-md-block', isDesktop); mobileEl.classList.toggle('d-md-none', isDesktop); } // 首次加载执行 toggleContent(); // 监听resize并防抖执行 window.addEventListener('resize', debounce(toggleContent, 250)); function debounce(func, wait) { let timeout; return function() { clearTimeout(timeout); timeout = setTimeout(func, wait); }; } </script> </body>
方法3:优先使用官方前端钩子
查看tanthammar/laravel-window-size官方文档,部分版本提供了前端事件钩子,可直接监听窗口尺寸变化并自动更新Session,优先采用官方方案。
内容的提问来源于stack exchange,提问作者Paul Godard
相关产品推荐
相关产品推荐

