You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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并局部刷新

  1. 添加防抖处理的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));
  1. 后端添加路由与控制器方法:
  • 路由(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'));
    }
}
  1. 创建内容片段视图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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:23:18