Vue.js(Quasar)项目中pdf.js调用getPage遇私有成员读取错误
Vue.js (Quasar) 使用 pdf.js getPage 时出现私有成员访问错误
问题详情
我在开发Vue.js(Quasar)项目时,使用pdf.js的getPage函数渲染PDF页面,遇到了无法访问私有成员的错误。我通过npm安装的是pdf.js 3.4.120版本,尝试使用官方示例的worker地址时,发现该地址指向3.5.97版本,版本不匹配导致问题无法解决。
代码实现
<template> <div> <canvas ref="canvas" height="100%" width="100%"></canvas> </div> </template> <script> import * as pdfjsLib from 'pdfjs-dist/build/pdf'; pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.4.120/pdf.worker.min.js'; export default { data() { return { pdf: null, currentPage: 1, numPages: 0, rendering: false, pageRenderingQueue: [] }; }, props: { src: { type: String, required: true }, pagesPerRender: { type: Number, default: 1 }, scale: { type: Number, default: 1 } }, mounted() { this.loadPdf(); }, methods: { async loadPdf() { let loadingTask = pdfjsLib.getDocument(this.src); loadingTask.promise.then(pdf => { console.log("pdf ", pdf); this.pdf = pdf; this.numPages = pdf.numPages; this.renderPages(); }).catch(error => { console.error('Failed to load PDF:', error); }); }, async renderPages() { if (this.rendering) { return; } this.rendering = true; const pagesToRender = []; for (let i = this.currentPage; i < Math.min(this.currentPage + this.pagesPerRender, this.numPages + 1); i++) { pagesToRender.push(i); } for (let i = 0; i < pagesToRender.length; i++) { const pageNumber = pagesToRender[i]; if (this.pageRenderingQueue.includes(pageNumber)) { continue; } this.pageRenderingQueue.push(pageNumber); this.pdf.getPage(pageNumber).then((page) => { this.handlePage(page); }); } }, handlePage(page){ const viewport = page.getViewport({ scale: this.scale }); const canvas = this.$refs.canvas; const context = canvas.getContext('2d'); canvas.width = viewport.width; canvas.height = viewport.height; const renderContext = { canvasContext: context, viewport: viewport }; const renderTask = page.render(renderContext); renderTask.then(() => { console.log("render task completed succesfully") const index = this.pageRenderingQueue.indexOf(pageNumber); this.pageRenderingQueue.splice(index, 1); if (this.pageRenderingQueue.length === 0) { this.rendering = false; } }); } } }; </script>
报错信息
Uncaught (in promise) TypeError: Cannot read private member #pagePromises from an object whose class did not declare it at Proxy.getPage (pdf.js?6178:2375:1) at Proxy.getPage (pdf.js?6178:1215:1) at Proxy.renderPages (PdfViewer.vue?772b:69:1) at eval (PdfViewer.vue?772b:46:1)
解决方案
1. 确保主库与Worker版本完全一致
错误的核心原因是pdf.js主库和worker版本不匹配,导致类的私有成员定义不一致。不要使用CDN地址,直接引用本地安装的worker文件:
// 替换原workerSrc配置 pdfjsLib.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.min.js');
2. 修复代码中的未定义变量问题
handlePage方法中使用了未定义的pageNumber变量,需要将其作为参数传入:
// 修改renderPages中的调用逻辑 this.pdf.getPage(pageNumber).then((page) => { this.handlePage(page, pageNumber); }); // 更新handlePage方法 handlePage(page, pageNumber){ const viewport = page.getViewport({ scale: this.scale }); const canvas = this.$refs.canvas; const context = canvas.getContext('2d'); canvas.width = viewport.width; canvas.height = viewport.height; const renderContext = { canvasContext: context, viewport: viewport }; const renderTask = page.render(renderContext); renderTask.then(() => { console.log("render task completed succesfully") const index = this.pageRenderingQueue.indexOf(pageNumber); this.pageRenderingQueue.splice(index, 1); if (this.pageRenderingQueue.length === 0) { this.rendering = false; } }); }
3. (可选)支持多页渲染
当前代码仅使用一个canvas,渲染多页时会覆盖内容。若需要显示多页,可以动态创建canvas元素:
// 在handlePage中动态创建canvas handlePage(page, pageNumber){ const viewport = page.getViewport({ scale: this.scale }); const canvas = document.createElement('canvas'); canvas.width = viewport.width; canvas.height = viewport.height; // 将canvas添加到页面容器中 this.$refs.pdfContainer.appendChild(canvas); const context = canvas.getContext('2d'); const renderContext = { canvasContext: context, viewport: viewport }; const renderTask = page.render(renderContext); renderTask.then(() => { console.log("render task completed succesfully") const index = this.pageRenderingQueue.indexOf(pageNumber); this.pageRenderingQueue.splice(index, 1); if (this.pageRenderingQueue.length === 0) { this.rendering = false; } }); }
同时在template中添加容器:
<template> <div ref="pdfContainer"></div> </template>
内容的提问来源于stack exchange,提问作者vitzi
相关产品推荐
相关产品推荐

