Vue】vue3.2中使用pdf.js踩坑:Cannot read from private field---pdf.js使用详解

本人项目中使用的是vue3.2+vite+ts,现在打算使用pdf.js库来加载预览pdf文件,下面是我的一些踩坑记录!真的太难受了!!!

1、安装pdf.js

骚瑞,版本不用考虑,直接cnpm就完事了

cnpm i pdfjs-dist

    
    
  • 1

在这里插入图片描述

2、踩坑坑

引入后控制台报错,报错内容翻译过来是:
Cannot read from private field读不到私有变量。

Cannot read from private field

    
    
  • 1

经排查是pdfDoc.getPage这里出了了问题:
vue3的proxy有关,

  • vue2是通过defineProperty来监听数据的改变和读取,
  • vue3是通过proxy来改变数据的。

但是在pdfjs-dist源码中,做了一个拦截校验,校验内容就是当前传入的参数,是否有obj对象,如果没有的话,直接抛出读不到私有变量错误。在之前老项目中,这样写是没有问题的:在pdfjs-dist拦截校验的时候,是一个MaskXXX(好像叫这个名字)的对象。在vue3中,pdfjs-dist拦截校验的时候,获取到的是一个proxy对象。

正确解法:pdfDoc.getPage的pdfDoc不要使用响应式写法!!!

此处参考一个文章:https://www.jianshu.com/p/1432ccd5089a

下面是正确写法,(代码略乱,后边再改成组件形式,显示只是测试讲解用)

<template>
	<div class="usinghelp-container">
		<div class="pdf-view">
        <canvas :id="`pdfCanvas${page}`" v-for="page in state.pdfPages" :key="page"></canvas>
	    </div>
	    <div class="pdf-bottom">我是操作区域</div>
	</div>
</template>

<script lang=ts setup name=usinghelp>
import { reactive, onMounted, nextTick } from ‘vue’;
import { ElMessage } from ‘element-plus’;
import * as PDF from “pdfjs-dist”;
import workerSrc from “pdfjs-dist/build/pdf.worker.entry.js”; // 引入时如果报红线错误,不影响运行, 或在index.d.ts中声明declare

const state = reactive<any>({
pdfPath: “/pdf/华康医疗公司简介.pdf”, //本地PDF文件路径放在/public中
pdfPages: ‘’, // 页数
pdfWidth: “”, // 宽度
pdfSrc: “”, // 地址
pdfScale: 1.0, // 放大倍数
});

// 此处为正确写法—原来我的参数用的响应式写法,就会报错Cannot read from private field
let pdfDoc:any = “”; // 文档内容—必须使用非响应式存储

// 页面加载时
onMounted(() => {
initTableData();
});

// 初始化表格数据
const initTableData = () => {
PDF.GlobalWorkerOptions.workerSrc = workerSrc;
console.log(“开始 pDF测试”);
console.log(workerSrc);
console.log(PDF);
console.log(“结束”);
loadFile(state.pdfPath);
};

// 加载pdf文件
const loadFile = (url: string) => {
let loadingTask = PDF.getDocument(url);
loadingTask.promise.then((pdf: any) => {
console.log(‘PDF loaded’);
debugger
pdfDoc = pdf;
state.pdfPages = pdf.numPages;
nextTick(() => {
renderPage(1); // 表示渲染第 1 页
});
});
}

// 渲染指定页面的内容
const renderPage = (num: number) => {
console.log(‘PDF 开始渲染’,num);
console.log(pdfDoc);
pdfDoc.getPage(num).then((page: any) => {
console.log(‘Page loaded’);
let canvas:any = document.getElementById(</span><span class="token string">pdfCanvas</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>num<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">);
let ctx = canvas.getContext(“2d”);
let dpr = window.devicePixelRatio || 1;
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
let ratio = dpr / bsr;
let viewport = page.getViewport({ scale: state.pdfScale });
canvas.width = viewport.width ratio;
canvas.height = viewport.height ratio;
// canvas.style.width = viewport.width + “px”;
// canvas.style.height = viewport.height + “px”;
canvas.style.width = “100%”;
canvas.style.height = “100%”;
state.pdfWidth = viewport.width + “px”;
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
// 将 PDF 页面渲染到 canvas 上下文中
let renderContext = {
canvasContext: ctx,
viewport: viewport,
};
page.render(renderContext);
if (state.pdfPages > num) {
renderPage(num + 1);
}
});
}
</script>

<style lang=scss scoped>
.usinghelp-container{
.pdf-view {
width: 80vw;
height: 80vh;
margin: 0 auto;
border: 1px solid #f90;
overflow: auto;
}
}
</style>

            <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/markdown_views-0407448025.css" rel="stylesheet">
            <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/style-bb308a51ed.css" rel="stylesheet">
    </div>
    <div id="treeSkill" style="display: block;"><div class="skill-tree-box"><div class="skill-tree-head">文章知识点与官方知识档案匹配,可进一步学习相关知识</div><div class="skill-tree-body"><div class="skill-tree-item"><span class="skill-tree-href"><a data-report-click="{&quot;spm&quot;:&quot;1001.2101.3001.6866&quot;,&quot;dest&quot;:&quot;https://edu.csdn.net/skill/vue/?utm_source=csdn_ai_skill_tree_blog&quot;}" href="https://edu.csdn.net/skill/vue/?utm_source=csdn_ai_skill_tree_blog" target="_blank">Vue入门技能树</a><i></i><a data-report-click="{&quot;spm&quot;:&quot;1001.2101.3001.6866&quot;,&quot;dest&quot;:&quot;https://edu.csdn.net/skill/vue/?utm_source=csdn_ai_skill_tree_blog&quot;}" href="https://edu.csdn.net/skill/vue/?utm_source=csdn_ai_skill_tree_blog" target="_blank">首页</a><i></i><a data-report-click="{&quot;spm&quot;:&quot;1001.2101.3001.6866&quot;,&quot;dest&quot;:&quot;https://edu.csdn.net/skill/vue/?utm_source=csdn_ai_skill_tree_blog&quot;}" href="https://edu.csdn.net/skill/vue/?utm_source=csdn_ai_skill_tree_blog" target="_blank">概览</a></span><span class="skill-tree-con"><span class="skill-tree-count">28668</span> 人正在系统学习中</span></div></div></div></div>
</article>
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值