iframe 渲染请求到的 html (邮件预览), 避免样式污染
背景:
之前弄了邮件系统, 但显示邮件内容时是直接 v-html , 导致邮件内容和项目样式互相污染; 之前代码是去掉邮件内容的样式文件, 结果导致部分内容显示错位, 现在想不改邮件内容, 用 iframe 包裹邮件内容显示
思路:
需要解决几个难点
- iframe 宽高如何随内容变化而变化
- iframe 如何与父级通讯
- 如何将不同类型的返回内容渲染成 html 放到 iframe 中
解决:
代码以 Vue 形式写的, 下面的代码是最终代码(iframe 渲染 + 自定义水平固定滚动条 + 打印 + 其他删除功能)拆分而来, 可能有些错漏/未删除变量
-
新建一个空白 HTML 页面, mailDetail.html , 只有最基本的 html 格式, 无任何内容
-
详情页新增 iframe 框, 引用此 html , 但先设置 height=“0” , 不显示内容
<!-- publicPath: process.env.BASE_URL --> <!-- mailFrameName: 'mailContentFrame' --> <iframe :src="`${publicPath}mailDetail.html`" :name="mailFrameName" width="100%" height="0" style="border: none;"></iframe>
-
请求到邮件内容, 并对邮件内容做了处理, 调用方法渲染邮件内容到 iframe 中
// 处理邮件详情代码并渲染到iframe中 renderCodeToIframe(mailContent) { /** handleMailHTML方法 和 renderMailHTML方法都来源mixins(mailContent) */ // 生成 iframe documentElement 代码 this.content = this.handleMailHTML(mailContent); // 渲染代码到 iframe 中 this.renderMailHTML(this.mailFrameName, this.content); },
-
渲染相关方法, from mixins(mailContent), 可以理解为提取出公共的方法到某处, 方便其他地方复用
-
对原始邮件内容做一些处理, 返回 html 字符串
handleMailHTML(mailContent) { // 解析邮件内容为 Document 对象 const parser = new DOMParser(); const doc = parser.parseFromString(mailContent, 'text/html'); // 邮件内容中的 base 标签会导致页面跳转时,指向 base 标签指定的地址,而非当前系统的页面,因此去除全部的 base 标签 Array.from(doc.querySelectorAll('base')).forEach(node => { node.remove(); }); // 邮件详情页的正文中超链接更改为新标签窗口打开 Array.from(doc.querySelectorAll('a')).forEach(node => { if (node.target && node.target !== '_blank') { node.target = '_blank'; } }); // 设置 body margin 默认为 0 , 避免浏览器默认样式给 body 加上 margin doc.body.style.margin = '0'; // 设置 body overflow-x hidden , 不允许出现横向滚动条 --- 外部模拟水平滚动条 doc.body.style['overflow-x'] = 'hidden'; // 设置 body overflow-y hidden + 去掉 body 的高度限制, 避免出现右侧滚动条 doc.body.style['overflow-y'] = 'hidden'; doc.body.style['min-height'] = 'auto'; doc.body.st
-