【react】动态页面转换成html文件下载,解决样式问题

发布时间:2023年12月18日

需求

今天遇到一个需求,挺恶心人的,将一个在线文档页面,可以导出成为html页面查看。

看到网上有使用fs模块,通过react的ReactDOMServer.renderToStaticMarkup将组件转成html字符串,输出文件了。
但是我尝试了,发现引入的fs为空,我就愁思,这个node环境下的模块,在react项目中能用么,一想到这里,自己真的是太笨了,肯定的不适用啊。fs是node模块,除非是next.js,不然用不了。

解决

思路类似,获取页面上渲染完成的dom字符串,通过a标签下载

URL.createObjectURL(file)

const fileName = `${name}.html`;
  const file = new File([htmlWithStyles], fileName, { type: 'text/html' });
  const oUrl = URL.createObjectURL(file);
  const a = document.createElement('a');
  a.style.setProperty('display', 'none');
  a.href = oUrl;
  a.download = file.name;
  document.body.appendChild(a);
  a.click();
  a.remove();
  const delay = 10000;
  setTimeout(() => URL.revokeObjectURL(oUrl), delay);

但是问题来了,发现下载的文件样式不存在 需要引入外部样式或者在写在style标签中

  const htmlWithStyles = `
  <html>
    <head>
    <style>${styles}</style>
    </head>
    <body>
      <div style="display:flex; height: 100%;">
      ${html}
      </div>
    </body>
  </html>
`;

笨人方法只有这样了,再高级点的,俺也不会

代码

这里的styles是外部定义的
要跟下载后的html里面的classname要对应,毕竟react项目跑起来的样式是加了很多前缀,比如这样
在这里插入图片描述
还有一个问题,就是使用的antd的表格,样式实在是太多了,但是还是要copy进去,不然静态页面样式就缺失了,从原本的页面里面,index.less进去,把所有的跟table相关的样式都copy过来。
在这里插入图片描述
在这里插入图片描述
所以说这个需求感觉没啥难度,但是又挺麻烦的。

封装方法

export function downHtmlFile({ html, name }) {
  // 创建包含外部样式链接的 HTML 字符串
  const htmlWithStyles = `
  <html>
    <head>
    <style>${styles}</style>
    </head>
    <body>
      <div style="display:flex; height: 100%;">
      ${html}
      </div>
    </body>
  </html>
`;
  const fileName = `${name}.html`;
  const file = new File([htmlWithStyles], fileName, { type: 'text/html' });
  const oUrl = URL.createObjectURL(file);
  const a = document.createElement('a');
  a.style.setProperty('display', 'none');
  a.href = oUrl;
  a.download = file.name;
  document.body.appendChild(a);
  a.click();
  a.remove();
  const delay = 10000;
  setTimeout(() => URL.revokeObjectURL(oUrl), delay);
}

在页面代码中使用

我是class组件,函数组件用useRef就好了,思路就是通过ref获取html字符串

 <div className={styles.con} ref={this.contentRef}>123</div>

	this.contentRef = createRef(); // 在构造方法中定义

  // 导出html文件
  handleExport = name => {
    const div = this.contentRef.current;
    if (!div) return;
    const html = div.innerHTML;
    downHtmlFile({ html, name });
  };

最后效果

在这里插入图片描述

文章来源:https://blog.csdn.net/silence_xiang/article/details/134856402
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。