Vue2或者uniapp 中 使用 iframe 嵌入本地 HTML 页面 并 相互通信。

1.使用 iframe 嵌入本地 HTML 页面(以pdfjs为例)

在 public 文件夹下新建 static 文件夹,然后将 html 文件及相关引用拷贝到 static 文件夹下

uniapp在src下新建hybrid文件

vue 文件完整代码

javascript 复制代码
<template>
  <div class="wrap">
    <iframe
      ref="iframe"
      :src="`${viewerUrl}?file=${encodeURIComponent(pdfUrl)}&page=12`"
      width="100%"
      height="50%"
      frameborder="0">
    </iframe>
    <button @click="vueSendMsg">vue向iframe传递信息</button>
    <button @click="iframeMethods">触发iframe中的方法</button>
  </div>
</template>

<script>export default {
  data() {
    return {
      viewerUrl:'/hybrid/html/web/viewer.html',  // vue2 这里 直接写 static ,static/web/viewer.html
    };
  },
  methods: {
    // vue获取iframe传递过来的信息
    getiframeMsg(event){
      const res = event.data;
      console.log(event)
      if(res.cmd == 'myIframe'){
        console.log(res)
      }
    },
    // vue向iframe传递信息
    vueSendMsg(){
      const iframeWindow = this.$refs.iframe.contentWindow;
      iframeWindow.postMessage({
        cmd:'myVue',
        params : {
          info: 'Vue向iframe传递的消息',
        }
      },'*')
    },
    // 触发iframe中的方法
    iframeMethods(){
      this.$refs.iframe.contentWindow.triggerByVue('通过Vue触发iframe中的方法');
    },
  },
  mounted() {
    window.addEventListener('message',this.getiframeMsg)
  },
};
</script>


<style lang="scss" scoped>.wrap{
  width: 100%;
  height: 500px;
}
</style>

html 文件完整代码

javascript 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <h3>iframe嵌入的页面</h3>
  <head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
		<meta name="google" content="notranslate">
		<title>PDF.js viewer</title>

		<!-- This snippet is used in production (included from viewer.html) -->
		<link rel="resource" type="application/l10n" href="locale/locale.json">
		<script src="../build/pdf.mjs" type="module"></script>

		<link rel="stylesheet" href="viewer.css">

		<!-- <script src="viewer.js" type="module"></script> -->
		<script type="module">
			const queryString = document.location.search.substring(1);
			function parseQueryString(query) {
				const params = new Map();
				for (const [key, value] of new URLSearchParams(query)) {
					params.set(key.toLowerCase(), value);
				}
				return params;
			}
			// 当前页码和pdf地址通过链接传进来
			const curParams = parseQueryString(queryString);
			var url = curParams.get("file"); // pdf 地址
			var {
				pdfjsLib
			} = globalThis;
			pdfjsLib.GlobalWorkerOptions.workerSrc = '../build/pdf.worker.mjs';
			
			var pdfDoc = null,
				pageNum =Number(curParams.get("curpage"))|| 1,  // 当前页码
				pageTotal=null, // 总页码
				pageRendering = false,
				pageNumPending = null,
				scale = 0.8,
				canvas = document.getElementById('the-canvas'),
				ctx = canvas.getContext('2d');
				
				// iframe获取Vue传递过来的信息 拿到进度存储的页码
				window.addEventListener("message", getVueMsg);
				function getVueMsg(event){
				  const res = event.data;
				  if(res.cmd == 'myVue'){
						pageNum=res.curPage;
				    console.log('iframe获取Vue传递过来的信息',res,res.curPage)
				  }
				};

			/**
			 * Get page info from document, resize canvas accordingly, and render page.
			 * @param num Page number.
			 */
			function renderPage(num) {
				pageRendering = true;
				// Using promise to fetch the page
				pdfDoc.getPage(num).then(function(page) {
					var viewport = page.getViewport({
						scale: scale
					});
					canvas.height = viewport.height;
					canvas.width = viewport.width;

					// Render PDF page into canvas context
					var renderContext = {
						canvasContext: ctx,
						viewport: viewport
					};
					var renderTask = page.render(renderContext);
					
					// Wait for rendering to finish
					renderTask.promise.then(function() {
						pageRendering = false;
						if (pageNumPending !== null) {
							// New page rendering is pending
							renderPage(pageNumPending);
							pageNumPending = null;
						}
					});
				});

				// Update page counters
				document.getElementById('page_num').textContent = num;
			}

			/**
			 * If another page rendering in progress, waits until the rendering is
			 * finised. Otherwise, executes rendering immediately.
			 */
			function queueRenderPage(num) {
				if (pageRendering) {
					pageNumPending = num;
				} else {
					renderPage(num);
				}
				iframeSendMsg(num,pageTotal); // 实时触发页码变化给 vue页面 
			}

			/**
			 * Displays previous page. 上一页
			 */
			function onPrevPage() {
				if (pageNum <= 1) {
					return;
				}
				pageNum--;
				queueRenderPage(pageNum);
			}
			document.getElementById('prev').addEventListener('click', onPrevPage);

			/**
			 * Displays next page. 下一页
			 */
			function onNextPage() {
				if (pageNum >= pdfDoc.numPages) {
					return;
				}
				pageNum++;
				queueRenderPage(pageNum);
			}
			document.getElementById('next').addEventListener('click', onNextPage);

			/**
			 * Asynchronously downloads PDF. 初次加载
			 */
			pdfjsLib.getDocument(url).promise.then(function(pdfDoc_) {
				pdfDoc = pdfDoc_;
				document.getElementById('page_count').textContent = pdfDoc.numPages;
        pageTotal=pdfDoc.numPages;
				// console.log('总页码',pageTotal)
				 iframeSendMsg(pageNum,pageTotal) // 初次加载后向cue页面传递 页码
				// Initial/first page rendering
				renderPage(pageNum);
			});
			
			// iframe向vue传递信息
			 window.iframeSendMsg = 	function iframeSendMsg(num,total){
			  window.parent.postMessage({
			    cmd:'myIframe',
				  pdfTotal:pageTotal,
			  readPage:num,
			    params : {
			       info: 'iframe向Vue传递的消息',
			     }
			  },'*');
			};
				
		</script>
		<script type="text/javascript">

		   function triggerByVue(msg){
		     console.log(msg)
		   }
		</script>

	</head>

	<body tabindex="1">
		<canvas id="the-canvas" style="width: 100%; height: 205;"></canvas>
		<div>
			<button id="prev">上一页并传给vue</button>
			<button id="next">下一页传给vue</button>
			&nbsp; &nbsp;
			<span>Page: <span id="page_num"></span> / <span id="page_count"></span></span>
		</div>
		<!-- <button onclick="iframeSendMsg()">iframe向Vue传消息</button> -->
	</body>

</body>

<script type="text/javascript">
  // iframe向vue传递信息
  function iframeSendMsg(){
    window.parent.postMessage({
      cmd:'myIframe',
      params : {
        info: 'iframe向Vue传递的消息',
      }
    },'*');
  };
  // iframe获取Vue传递过来的信息
  window.addEventListener("message", getVueMsg);
  function getVueMsg(event){
    const res = event.data;
    if(res.cmd == 'myVue'){
      console.log(res)
    }
  };
  function triggerByVue(msg){
    console.log(msg)
  }
</script>
</html>
相关推荐
Fan_web1 小时前
JavaScript高级——闭包应用-自定义js模块
开发语言·前端·javascript·css·html
冯宝宝^1 小时前
基于mongodb+flask(Python)+vue的实验室器材管理系统
vue.js·python·flask
平凡シンプル2 小时前
安卓 uniapp跨端开发
android·uni-app
cc蒲公英2 小时前
Vue2+vue-office/excel 实现在线加载Excel文件预览
前端·vue.js·excel
森叶2 小时前
Electron-vue asar 局部打包优化处理方案——绕开每次npm run build 超级慢的打包问题
vue.js·electron·npm
小小竹子2 小时前
前端vue-实现富文本组件
前端·vue.js·富文本
青稞儿3 小时前
面试题高频之token无感刷新(vue3+node.js)
vue.js·node.js
艾小逗4 小时前
uniapp快速入门教程,内容来源于官方文档,仅仅记录快速入门需要了解到的知识点
小程序·uni-app·app·es6
程序员凡尘4 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js
Bug缔造者9 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js