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

如何用JavaScript获取分页列表中所有页面的li元素并导出PDF

如何导出分页卡片列表的所有项为PDF?

我有一个带分页功能的卡片区域,本质是无序列表(ul)中的<li>元素。因为<li>数量多,设置了分页,用户可点击next按钮切换查看。现在想获取所有列表项并导出为PDF,但当前JavaScript代码只能打印第一页,请问怎么实现获取多页的<li>元素?


现有代码

HTML代码

<ul class="a-CardView-items a-CardView-items--grid2col LAYOUT-CLASS col-sm-12 mb-3">
    <li class="a-CardView-item col-sm-6" data-id="4" data-rownum="1">
        <div
            class="a-CardView has-title has-subtitle has-body has-secondary has-badge has-media has-media--body has-media--square has-media--cover CARD-CLASS">
            <div
                class="a-CardView-media a-CardView-media--body a-CardView-media--square a-CardView-media--cover MEDIA-CLASS">
                <img class="a-CardView-mediaImg"
                    src="https://images.pexels.com/photos/1407305/pexels-photo-1407305.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
                    alt="Photo of Fms" loading="lazy">
            </div>
            <div class="a-CardView-header">
                <div class="a-CardView-headerBody">
                    <h3 class="a-CardView-title TITLE-CLASS">Fr Ad</h3>
                    <h4 class="a-CardView-subTitle SUBTITLE-CLASS">test4@gmail.com</h4>
                </div>
                <div class="a-CardView-badge BADGE-CLASS" title="C 133">
                    <span class="a-CardView-badgeLabel">Class</span> <span class="a-CardView-badgeValue">133</span>
                </div>
            </div>
            <div class="a-CardView-body">
                <div class="a-CardView-mainContent">
                    <div class="a-CardView-mainContent BODY-CLASS chip  item-status" key="4"></div>
                </div>
                <div class="a-CardView-subContent BODY-CLASS chip">New Candidates</div>
            </div>
        </div>
    </li>
    <li class="a-CardView-item col-sm-6" data-id="48" data-rownum="2">
        <div
            class="a-CardView has-title has-subtitle has-body has-secondary has-badge has-media has-media--body has-media--square has-media--cover CARD-CLASS">
            <div
                class="a-CardView-media a-CardView-media--body a-CardView-media--square a-CardView-media--cover MEDIA-CLASS">
                <img class="a-CardView-mediaImg"
                    src="https://images.pexels.com/photos/1407305/pexels-photo-1407305.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
                    alt="Photo ena" loading="lazy">
            </div>
            <div class="a-CardView-header">
                <div class="a-CardView-headerBody">
                    <h3 class="a-CardView-title TITLE-CLASS">Jo Ba</h3>
                    <h4 class="a-CardView-subTitle SUBTITLE-CLASS">test3@gmail.com</h4>
                </div>
                <div class="a-CardView-badge BADGE-CLASS" title="C 133">
                    <span class="a-CardView-badgeLabel">Class</span> <span class="a-CardView-badgeValue">133</span>
                </div>
            </div>
            <div class="a-CardView-body">
                <div class="a-CardView-mainContent">
                    <div class="a-CardView-mainContent BODY-CLASS chip  item-status" key="48"></div>
                </div>
                <div class="a-CardView-subContent BODY-CLASS chip">New Candidates</div>
            </div>
        </div>
    </li>
</ul>

JavaScript代码

var btn = document.getElementById("print_btn");
//var createpdf = document.getElementsByClassName('LAYOUT-CLASS');
var createpdf = document.getElementById('export_candidates_Cards');
//var createpdf = document.querySelectorAll('.a-CardView-item ');
//var number_of_card = document.getElementById('test').getAttribute('pageLength');
console.log(createpdf);
var opt = {
         margin: 0,
         filename: 'Candiates.pdf',
         html2canvas: { 
            scale: 2
         },
         jsPDF: {
            unit: 'in',
            format: 'A4',
            orientation: 'portrait'   
         },
         pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
};

html2pdf().set(opt).from(createpdf).save();

解决方案

方法1:临时拼接所有卡片到隐藏容器再导出

核心思路是模拟加载所有分页的卡片,把它们放到一个临时的隐藏DOM容器里,再用html2pdf导出这个容器,导出完成后销毁临时容器。

document.getElementById("print_btn").addEventListener("click", async function() {
    // 创建临时容器
    const tempContainer = document.createElement('ul');
    tempContainer.className = 'a-CardView-items a-CardView-items--grid2col LAYOUT-CLASS col-sm-12 mb-3';
    tempContainer.style.position = 'absolute';
    tempContainer.style.top = '-9999px';
    tempContainer.style.left = '-9999px';
    document.body.appendChild(tempContainer);

    try {
        // 替换成实际总页数
        const totalPages = 5; 
        // 替换成你的next按钮选择器
        const nextBtn = document.querySelector('.pagination-next-btn'); 

        // 克隆当前页卡片到临时容器
        const currentItems = document.querySelectorAll('.a-CardView-item');
        currentItems.forEach(item => tempContainer.appendChild(item.cloneNode(true)));

        // 循环切换分页,克隆每一页卡片
        for (let i = 1; i < totalPages; i++) {
            nextBtn.click();
            // 等待页面渲染完成,可根据实际情况调整等待时间
            await new Promise(resolve => setTimeout(resolve, 500));
            const pageItems = document.querySelectorAll('.a-CardView-item');
            pageItems.forEach(item => tempContainer.appendChild(item.cloneNode(true)));
        }

        // 导出PDF
        const opt = {
            margin: 0,
            filename: 'Candiates.pdf',
            html2canvas: { scale: 2 },
            jsPDF: { unit: 'in', format: 'A4', orientation: 'portrait' },
            pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
        };
        await html2pdf().set(opt).from(tempContainer).save();
    } catch (err) {
        console.error('导出失败:', err);
    } finally {
        // 销毁临时容器
        document.body.removeChild(tempContainer);
    }
});

方法2:直接从数据源渲染所有卡片

如果分页数据是从接口获取的,最优方案是直接请求所有数据,渲染一个包含所有卡片的隐藏列表再导出,避免DOM切换的等待问题。

document.getElementById("print_btn").addEventListener("click", async function() {
    // 创建临时容器
    const tempContainer = document.createElement('ul');
    tempContainer.className = 'a-CardView-items a-CardView-items--grid2col LAYOUT-CLASS col-sm-12 mb-3';
    tempContainer.style.position = 'absolute';
    tempContainer.style.top = '-9999px';
    tempContainer.style.left = '-9999px';
    document.body.appendChild(tempContainer);

    try {
        // 请求所有数据,替换成你的实际接口
        const response = await fetch('/api/get-all-candidates');
        const allCandidates = await response.json();

        // 遍历数据渲染所有卡片
        allCandidates.forEach(candidate => {
            const li = document.createElement('li');
            li.className = 'a-CardView-item col-sm-6';
            li.dataset.id = candidate.id;
            li.dataset.rownum = candidate.rownum;
            li.innerHTML = `
                <div class="a-CardView has-title has-subtitle has-body has-secondary has-badge has-media has-media--body has-media--square has-media--cover CARD-CLASS">
                    <div class="a-CardView-media a-CardView-media--body a-CardView-media--square a-CardView-media--cover MEDIA-CLASS">
                        <img class="a-CardView-mediaImg" src="${candidate.imageUrl}" alt="${candidate.name}" loading="lazy">
                    </div>
                    <div class="a-CardView-header">
                        <div class="a-CardView-headerBody">
                            <h3 class="a-CardView-title TITLE-CLASS">${candidate.name}</h3>
                            <h4 class="a-CardView-subTitle SUBTITLE-CLASS">${candidate.email}</h4>
                        </div>
                        <div class="a-CardView-badge BADGE-CLASS" title="C ${candidate.classNum}">
                            <span class="a-CardView-badgeLabel">Class</span> <span class="a-CardView-badgeValue">${candidate.classNum}</span>
                        </div>
                    </div>
                    <div class="a-CardView-body">
                        <div class="a-CardView-mainContent">
                            <div class="a-CardView-mainContent BODY-CLASS chip item-status" key="${candidate.id}"></div>
                        </div>
                        <div class="a-CardView-subContent BODY-CLASS chip">${candidate.status}</div>
                    </div>
                </div>
            `;
            tempContainer.appendChild(li);
        });

        // 导出PDF
        const opt = {
            margin: 0,
            filename: 'Candiates.pdf',
            html2canvas: { scale: 2 },
            jsPDF: { unit: 'in', format: 'A4', orientation: 'portrait' },
            pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
        };
        await html2pdf().set(opt).from(tempContainer).save();
    } catch (err) {
        console.error('导出失败:', err);
    } finally {
        document.body.removeChild(tempContainer);
    }
});

方法3:临时取消分页显示所有卡片

如果分页是通过CSS类控制显示隐藏的,可以临时移除分页控制类,显示所有卡片后导出,导出完成再恢复原状态。

document.getElementById("print_btn").addEventListener("click", async function() {
    const listContainer = document.querySelector('.LAYOUT-CLASS');
    // 保存原有的分页相关类
    const originalClasses = listContainer.className;
    // 移除分页控制类,替换成你的实际分页控制类
    listContainer.classList.remove('pagination-controlled'); 

    try {
        // 等待DOM更新
        await new Promise(resolve => setTimeout(resolve, 300));
        // 导出当前容器
        const opt = {
            margin: 0,
            filename: 'Candiates.pdf',
            html2canvas: { scale: 2 },
            jsPDF: { unit: 'in', format: 'A4', orientation: 'portrait' },
            pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
        };
        await html2pdf().set(opt).from(listContainer).save();
    } catch (err) {
        console.error('导出失败:', err);
    } finally {
        // 恢复原有的类
        listContainer.className = originalClasses;
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 11:05:55