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

Laravel单视图中如何展示数据列表与数据详情

解决列表与详情同页展示的问题

不用再次循环所有文章啦!你现在的问题是详情区的$post没有对应到用户点击的具体文章,咱们分几种方案来实现,选适合你的就行:

方案一:AJAX动态加载详情(适合文章数量多的场景)

这种方式初始只加载列表,点击时再请求对应文章的详情,能减少页面初始加载体积。

1. 修改列表项,添加文章标识

把列表里的<a>标签改成带文章ID的点击触发元素,避免页面跳转:

<a class="grid__item" href="javascript:void(0)" data-post-id="{{ $post->id }}">
    <h2 class="title title--preview">{{$post->title}}</h2>
    <span class="category">{{$post->title}}</span>
    <div class="loader"></div>
    <div class="meta meta--preview">
        <img class="meta__avatar" src="{{ Voyager::image( $post->image ) }}" alt="{{$post->title}}" />
        <span class="meta__date"><i class="fa fa-calendar-o"></i>{{$post->created_at->format('m-d-Y')}}</span>
        <span class="meta__reading-time"><i class="fa fa-clock-o"></i>{{$post->created_at->format('H:i')}}</span>
    </div>
</a>

2. 改造详情区域为动态模板

先留空或者默认显示第一篇文章的内容:

<section class="content" id="postContent">
    <div class="scroll-wrap">
        <article class="content__item" id="postDetail">
            @if($posts->isNotEmpty())
                <!-- 默认显示第一篇 -->
                <span class="category category--full">{{ $posts[0]->title }}</span>
                <h2 class="title title--full">{{ $posts[0]->title }}</h2>
                <div class="meta meta--full">
                    <img class="meta__avatar" src="{{ Voyager::image( $posts[0]->image ) }}" alt="{{ $posts[0]->title }}" />
                    <span class="meta__author">{{ $posts[0]->author ?? $posts[0]->title }}</span>
                    <span class="meta__date"><i class="fa fa-calendar-o"></i>{{ $posts[0]->created_at->format('m/d/Y') }}</span>
                    <span class="meta__reading-time"><i class="fa fa-clock-o"></i>{{ $posts[0]->created_at->format('H:i') }}</span>
                </div>
                <div class="post-content">{!! $posts[0]->content !!}</div>
            @endif
        </article>
    </div>
    <button class="close-button"><i class="fa fa-close"></i><span>Close</span></button>
</section>

3. 写JS实现点击加载逻辑

用原生JS就能搞定,不需要额外依赖:

const postItems = document.querySelectorAll('.grid__item');
const postDetail = document.getElementById('postDetail');
const closeBtn = document.querySelector('.close-button');
const contentSection = document.getElementById('postContent');

// 给每个列表项绑定点击事件
postItems.forEach(item => {
    item.addEventListener('click', async () => {
        const postId = item.dataset.postId;
        
        // 发请求拿文章详情(需要后端对应接口)
        const res = await fetch(`/posts/${postId}`);
        const post = await res.json();
        
        // 填充详情内容
        postDetail.innerHTML = `
            <span class="category category--full">${post.title}</span>
            <h2 class="title title--full">${post.title}</h2>
            <div class="meta meta--full">
                <img class="meta__avatar" src="${post.image_url}" alt="${post.title}" />
                <span class="meta__author">${post.author ?? post.title}</span>
                <span class="meta__date"><i class="fa fa-calendar-o"></i>${new Date(post.created_at).toLocaleDateString()}</span>
                <span class="meta__reading-time"><i class="fa fa-clock-o"></i>${new Date(post.created_at).toLocaleTimeString()}</span>
            </div>
            <div class="post-content">${post.content}</div>
        `;
        
        // 显示详情区
        contentSection.style.display = 'block';
    });
});

// 关闭按钮逻辑
closeBtn.addEventListener('click', () => {
    contentSection.style.display = 'none';
});

4. 后端准备接口(Laravel示例)

在PostController里加一个返回文章详情的方法:

public function show(Post $post)
{
    // 处理Voyager图片路径
    $post->image_url = Voyager::image($post->image);
    return response()->json($post);
}

然后在路由文件(web.php或api.php)加一条路由:

Route::get('/posts/{post}', [PostController::class, 'show']);

方案二:提前渲染所有详情(适合文章数量少的场景)

这种方式一次性把所有文章详情都渲染到页面,通过CSS控制显示隐藏,不用发AJAX请求:

1. 渲染所有文章详情

把详情区改成循环渲染每个文章的内容,默认只显示第一篇:

<section class="content">
    <div class="scroll-wrap">
        @foreach($posts as $index => $post)
            <article class="content__item {{ $index === 0 ? 'active' : 'hidden' }}" id="post-{{ $post->id }}">
                <span class="category category--full">{{ $post->title }}</span>
                <h2 class="title title--full">{{ $post->title }}</h2>
                <div class="meta meta--full">
                    <img class="meta__avatar" src="{{ Voyager::image( $post->image ) }}" alt="{{ $post->title }}" />
                    <span class="meta__author">{{ $post->author ?? $post->title }}</span>
                    <span class="meta__date"><i class="fa fa-calendar-o"></i>{{ $post->created_at->format('m/d/Y') }}</span>
                    <span class="meta__reading-time"><i class="fa fa-clock-o"></i>{{ $post->created_at->format('H:i') }}</span>
                </div>
                <div class="post-content">{!! $post->content !!}</div>
            </article>
        @endforeach
    </div>
    <button class="close-button"><i class="fa fa-close"></i><span>Close</span></button>
</section>

2. 添加CSS控制显示隐藏

.content__item.hidden {
    display: none;
}
.content__item.active {
    display: block;
}

3. 写JS切换显示

const postItems = document.querySelectorAll('.grid__item');
const closeBtn = document.querySelector('.close-button');
const contentSection = document.querySelector('.content');

postItems.forEach(item => {
    item.addEventListener('click', () => {
        const postId = item.dataset.postId;
        
        // 隐藏所有详情
        document.querySelectorAll('.content__item').forEach(detail => {
            detail.classList.add('hidden');
            detail.classList.remove('active');
        });
        
        // 显示对应文章的详情
        document.getElementById(`post-${postId}`).classList.remove('hidden');
        document.getElementById(`post-${postId}`).classList.add('active');
        
        contentSection.style.display = 'block';
    });
});

closeBtn.addEventListener('click', () => {
    contentSection.style.display = 'none';
});

两种方案各有优劣,根据你的文章数量和需求选就行~

内容的提问来源于stack exchange,提问作者madiluzi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:04:31