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

Razor Pages中为Partial View实现客户端分页求助

需求说明

我是Razor Pages初学者,当前功能是点击侧边栏Movies标签显示电影表格,搜索后通过Partial View更新数据。现在需要给初始展示的数据和Partial View添加客户端分页,总共有5000条数据,要求每页显示25条。尝试过Bootstrap Table但没成功,希望用jQuery和Ajax实现,以下是现有代码:

Movies.cshtml

@page
@using Project.Models;
@model Project.Pages.MovieModel

@section scripts {
    <script src="/UnwatchedMovies.js"></script>
}

<div class="container">
    <div class="col-12">
        <h2> Movie Search </h2>
    </div>
</div>

<div>
    <form method="post" id="movies">
        <div class="row">
            <input type="text" id="searchInput"/>
            <button type="button" id="searchButton" onclick="searchMovies()"></button>  
        </div>
        <div class="row">
            <label class="switch">
                <input type="checkbox" id="toggleMovies" onchange="searchMovies()">
                <div class="slider"></div>
            </label>    
        </div>
    </form>

    <div id="movieDataPartialView">
        @await Html.PartialAsync("Movies/_MovieDataPartial",Model.Movies)
    </div>
</div>

Movies.cshtml.cs

namespace Movies.Pages
{
    public class MovieModel : PageModel
    {
        private readonly UnwatchedMovies _unwatchedMovies;
        public MovieModel(UnwatchedMovies unwatchedMovies)
        {
            _unwatchedMovies = unwatchedMovies;
        }
        public List<Movie> Movies {get; set;}

        public void OnGet()
        {
            Movies = _unwatchedMovies.GetMovies(null);
        }

        public PartialViewResult OnPostSearch([FromBody] Search search) 
        {
            Movies = _unwatchedMovies.GetMovies(search);
            return new PartialViewResult
            {
                ViewName = "Movies/_MovieDataPartial",
                ViewData = new ViewDataDictionary<List<Movie>>(ViewData, Movies)
            };
        }
    }
}

_MovieDataPartial.cshtml(Partial View)

@model List<Project.Models.Movie>

<div>
    <table id="tableData">
        <thead>
            <tr>
                <th scope="col">Name</th>
                <th scope="col">Ratings</th>
                <th scope="col">Genre</th>
            </tr>
        </thead>
        <tbody id="bodyData">
            @foreach(var movie in Model)
            {
                <td>@movie.Name</td>
                <td>@movie.Ratings</td>
                <td>@movie.Genre</td>
            }
        </tbody>
    </table>
</div>

解决方案实现步骤

1. 修复Partial View结构并添加分页容器

先修正原Partial View中表格行的结构缺失问题,同时添加分页控件容器:

@model List<Project.Models.Movie>

<div>
    <table id="tableData" class="table table-striped">
        <thead>
            <tr>
                <th scope="col">Name</th>
                <th scope="col">Ratings</th>
                <th scope="col">Genre</th>
            </tr>
        </thead>
        <tbody id="bodyData">
            @foreach(var movie in Model)
            {
                <tr>
                    <td>@movie.Name</td>
                    <td>@movie.Ratings</td>
                    <td>@movie.Genre</td>
                </tr>
            }
        </tbody>
    </table>
    <!-- 分页控件容器 -->
    <div id="paginationControls" class="mt-3"></div>
</div>

2. 编写客户端分页逻辑(UnwatchedMovies.js)

用jQuery实现全量数据存储、分页计算、页面渲染和搜索联动:

$(document).ready(function() {
    // 全局变量存储全量电影数据与分页参数
    let allMovies = [];
    const pageSize = 25;
    let currentPage = 1;

    // 初始化:提取页面加载时的电影数据
    allMovies = $("#bodyData tr").map(function() {
        return {
            name: $(this).find("td").eq(0).text(),
            ratings: $(this).find("td").eq(1).text(),
            genre: $(this).find("td").eq(2).text()
        };
    }).get();

    // 初始化分页控件与当前页数据
    renderPagination();
    renderCurrentPage();

    // 搜索电影函数(替换原有逻辑)
    window.searchMovies = function() {
        const searchText = $("#searchInput").val().trim();
        const toggleChecked = $("#toggleMovies").is(":checked");

        $.ajax({
            url: "/Movies?handler=Search",
            type: "POST",
            contentType: "application/json",
            data: JSON.stringify({
                searchText: searchText,
                toggleState: toggleChecked // 匹配你的Search模型字段,按需调整
            }),
            success: function(response) {
                // 解析返回的Partial View,提取全量电影数据
                const tempTable = $(response).find("#bodyData");
                allMovies = $(tempTable).find("tr").map(function() {
                    return {
                        name: $(this).find("td").eq(0).text(),
                        ratings: $(this).find("td").eq(1).text(),
                        genre: $(this).find("td").eq(2).text()
                    };
                }).get();

                // 重置分页到第一页,重新渲染
                currentPage = 1;
                renderPagination();
                renderCurrentPage();
            },
            error: function(xhr) {
                console.error("搜索请求失败:", xhr.responseText);
            }
        });
    };

    // 渲染当前页数据
    function renderCurrentPage() {
        const startIndex = (currentPage - 1) * pageSize;
        const endIndex = startIndex + pageSize;
        const currentMovies = allMovies.slice(startIndex, endIndex);

        $("#bodyData").empty();
        currentMovies.forEach(movie => {
            const row = `<tr>
                <td>${movie.name}</td>
                <td>${movie.ratings}</td>
                <td>${movie.genre}</td>
            </tr>`;
            $("#bodyData").append(row);
        });
    }

    // 生成分页控件
    function renderPagination() {
        const totalPages = Math.ceil(allMovies.length / pageSize);
        const paginationContainer = $("#paginationControls");
        paginationContainer.empty();

        if (totalPages <= 1) return;

        // 上一页按钮
        const prevButton = `<button class="btn btn-outline-primary me-1" ${currentPage === 1 ? 'disabled' : ''} onclick="changePage(${currentPage - 1})">上一页</button>`;
        paginationContainer.append(prevButton);

        // 动态显示页码(最多显示5个)
        let startPage = Math.max(1, currentPage - 2);
        let endPage = Math.min(totalPages, currentPage + 2);
        if (totalPages < 5) {
            startPage = 1;
            endPage = totalPages;
        }

        for (let i = startPage; i <= endPage; i++) {
            const pageButton = `<button class="btn btn-primary me-1 ${i === currentPage ? 'active' : ''}" onclick="changePage(${i})">${i}</button>`;
            paginationContainer.append(pageButton);
        }

        // 下一页按钮
        const nextButton = `<button class="btn btn-outline-primary" ${currentPage === totalPages ? 'disabled' : ''} onclick="changePage(${currentPage + 1})">下一页</button>`;
        paginationContainer.append(nextButton);
    }

    // 切换页面函数
    window.changePage = function(pageNum) {
        const totalPages = Math.ceil(allMovies.length / pageSize);
        if (pageNum < 1 || pageNum > totalPages) return;
        currentPage = pageNum;
        renderPagination();
        renderCurrentPage();
    };
});

3. 后端确认(确保返回全量数据)

保证UnwatchedMovies.GetMovies()方法返回所有符合条件的电影数据,不做服务端分页,因为我们要在客户端处理分页逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:02:05