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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 11:03:09