DOMException: Failed to construct ‘Worker‘, 乾坤框架中子应用vue-pdf预览在主应用报错处理办法,其他文件预览同理

这个问题的出现,其实是chrome浏览器安全机制导致,不允许在本地直接运行,它会当作跨域访问。
既然我们是打算做pdf的预览功能,那么我们就可以用这样的一个思路:

1、跨域问题既然是因为浏览器安全机制导致,那么我们就绕过他,使用iframe,来请求加载主应用的文件,主应用项目,预览pdf:

<template>
    <div>
        <pdf v-for="item in numPages" :key="item" :src="pdfSrc" :page="item" />
    </div>
</template>
<script>
import pdf from 'vue-pdf';
import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory.js';
import {ospdetail} from '@/api/comment.js';
export default {
    name: 'ispdf',
    components: {
        pdf
    },
    data() {
        return {
            numPages: 0,
            pdfSrc: ''
        };
    },
    created() {
        window.addEventListener('message', event => {
            console.log('event',event);
            if(event.data.type == 'docxPreview'){
                this.getTitlePdfurl(event.data.data)
            }
            
        });
    },
    methods: {
        getTitlePdfurl(urls) {
            this.pdfSrc = pdf.createLoadingTask({ url: urls, CMapReaderFactory }); //解决中文乱码问题
            this.pdfSrc.promise.then(pdf => {
                this.numPages = pdf.numPages;
            });
        }
    }
};
</script>

那我们要怎么在子应用中找到这个主应用的文件呢,路由呗,在主应用的路由文件中注册它,那么主应用的准备就做好了

{
        path: '/preview',
        component: resolve => require(['@/views/preview/ispdf.vue'], resolve),
        hidden: true
    },

2、然后在子组件中就是先办法找到主应用pdf文件,并加以利用

通过DpfSlot来条件判断,当前是在子应用本地(preview ),还是在主应用打开的,
通过乾坤框架的window.POWERED_BY_QIANKUN,来区分,true是主应用,在子应用则是undefined

<preview v-if="DpfSlot" ref="previews"></preview>
 <iframe
     v-else
     :src="`/preview?id=${iframeId}`"
     class="preview-iframe"
     style="width: 100%;height: 99%;"
     ref="previewIframe"
 ></iframe>
 <script>
 components: {//子应用本地dpf文件
        preview: window.__POWERED_BY_QIANKUN__ ?'':() =>import('./component/ispdf.vue') 
    },
 computed: {
            DpfSlot() {
                if( window.__POWERED_BY_QIANKUN__) {
                    return false
                }else {
                    return true
                }
            }

},
 </script>

3、那么关联子应用代码和主应用代码的方式如下:
在子应用中,通过iframe的src去找到主应用注册的文件路由

<iframe
     v-else
     :src="`/preview?id=${iframeId}`"
     class="preview-iframe"
     style="width: 100%;height: 99%;"
     ref="previewIframe"
 ></iframe>

此方法为下拉框change方法,用于切换pdf,后面会有截图片段
得到isurl,用iframe的this.$refs.previewIframe.contentWindow.postMessage,将pdf文件流传递出去。

handleSelect(rowid) {
        var fileData
        this.xzydbg.forEach((item,i)=> {
            if(item.id === rowid) {
                fileData = item.data
            }
        })
        var isurl = `data:application/pdf;base64,`+fileData
        if( window.__POWERED_BY_QIANKUN__ ) {
                    this.$refs.previewIframe.contentWindow.postMessage(
                        {
                            type: "docxPreview",
                            data: isurl,
                        },
                        "*"
                    );
                }else {
                        this.$refs.previews.getTitlePdfurl(isurl)
                }
    },

流是发出去了,那主应用是怎么接受的呢,主应用封装中有这样的代码:
通过注册一个message监听便可

created() {
        window.addEventListener('message', event => {
            console.log('event',event);
            if(event.data.type == 'docxPreview'){
                this.getTitlePdfurl(event.data.data)
            }
            
        });
    },

这样就是一个完成的思路了。配个简图:
在这里插入图片描述

下面是实际开发时遇到的问题以及解决办法:

在初次打开阅读报告弹窗时,出现了加载顺序问题,本来是把数据传递写在接口内的,可是发现等接口跑完,发送,主应用未能监听到消息,退而求其次,选择用路由的方式把渲染的pdf对象的id给主应用(iframeId ),

子应用打开弹窗
handleOpenAddDialog(row) {//进入阅读报告
        this.addDialog.title = '阅读报告';
        this.iframeId = row.id;
        this.addDialog.visible = true;
        //如果是主应用代开,那么就这个接口就只服务于下拉选内容,但是在子应用本地,也依然起到了完整的效果
        ospdetail({dataId:row.id}).then(res=> {
                if(res.code===200) {
                    this.xzydbg = res.data
                    this.addDialog.formData.paramId = this.xzydbg[0].id
                    var isurl = `data:application/pdf;base64,`+this.xzydbg[0].data
                    if( !window.__POWERED_BY_QIANKUN__ ) {this.$refs.previews.getTitlePdfurl(isurl)}
                    
                }
            })
        // if( window.__POWERED_BY_QIANKUN__ ) {
        //     this.$refs.previewIframe.contentWindow.postMessage(
        //         {
        //             type: "docxPreview",
        //             dataId:row.id
        //         },
        //         "*"
        //     );
        // }
        
            
        
    },

主应用文件里就变成了这样
主应用项目可以兼容所有子应用接口,所以调接口解决初次打开弹窗的预览问题,
后续下拉切换pdf,依然选择用消息监听的方式

created() {
        console.log(this.$route.query.id);
        ospdetail({dataId:this.$route.query.id}).then(res=> {
                    if(res.code===200) {
                        var isurl = `data:application/pdf;base64,`+res.data[0].data
                        this.getTitlePdfurl(isurl)
                    }
                })
        window.addEventListener('message', event => {
            console.log('event',event);
            if(event.data.type == 'docxPreview'){
                this.getTitlePdfurl(event.data.data)
            }
            
        });
    },
    methods: {
        getTitlePdfurl(urls) {
            this.$set(this,'pdfSrc',pdf.createLoadingTask({ url: urls, CMapReaderFactory }))
            // this.pdfSrc = pdf.createLoadingTask({ url: urls, CMapReaderFactory }); //解决中文乱码问题
            this.pdfSrc.promise.then(pdf => {
                this.numPages = pdf.numPages;
            });
        }
    }
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值