【JS】如何保证样式无损的下载一个页面为.html文件

发布时间:2024年01月22日

【JS】如何保证样式无损的下载一个页面

需求

现在有一个报告页面,需要前端直接将报告内容下载为一个html文件,并且可以脱机打开,样式与页面保持一致。

分析与方案

1.首先,单独写一个.css文件,让页面与下载的html文件都使用的思路肯定是可行的;但是我的页面使用VUE+less开发,同时有大量的公共样式,剥离出一个.CSS文件的难度极大。
2.一个页面无非由 .html .css .js三部分构成;我们只需要将这个页面用到的三部分都下载下来,并保持正确的路径与依赖关系,就能够将一个页面完整复刻。

对于笔者来说,方案2可行性更高且通用性更高;当然,笔者的需求只需要下载一个可以观看的报告,对与JS文件没有需求,所以实现代码会跳过.JS文件。不过有需要的话可以以相同思路实现即可。

代码实现

downloadHtml(){
			//初始化css
 			let css = '';
 			//笔者因为页面使用rem为单位,所以需要一个初始化html元素font-size的方法;因为这个方法没有单独抽离文件且较为简单,笔者选择在下载时手动添加;
            let js = `
            function setFontSize() {
    const designWidth = 1920; //设计稿的宽度,根据实际项目调整
    const fontSize = document.documentElement.clientWidth / designWidth * 100;
    document.querySelector('html').style.fontSize = fontSize + 'px';
}
function debounce(func, wait) {
    let timeout;
    return function() {
        const context = this;
        const args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            func.apply(context, args);
        }, wait);
    };
}
window.onresize = function () {
    setFontSize()
};
setFontSize();`;
			//直接写入script这样的字符串会有问题,将它从中间拆分再拼接可以避免
			//将要执行的js通过<script>标签包裹,准备插入html,如果需要下载页面的js也可以使用该思路;
            js = '<scr' + 'ipt>' + js + '</scr' + 'ipt>';
            //获取该页面用到的.css静态资源地址
            const stylesheets = Array.from(document.getElementsByTagName('link'))
                .filter((link) => link.rel === 'stylesheet')
                .map((link) => link.href);
            //下载所有的.css静态资源
            Promise.all(
                stylesheets.map((href) => {
                    return fetch(href).then((response) => response.text());
                })
            ).then((cssTexts) => {
            	//当.css静态资源下载完成,将其通过<style>标签包裹的方式插入html文件
                css += cssTexts.join('\n');
                css = '<style>' + css + '</style>';
                // 获取Vue实例的HTML内容
                const html = document.getElementById('htmlDetail').outerHTML;
                const blob = new Blob([html, '\n', css, '\n', js], {
                    type: 'text/html'
                });

                // 创建一个a标签用于下载
                const a = document.createElement('a');
                a.href = URL.createObjectURL(blob);
                a.download = 'vue-element.html';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
            });
}

问题与待优化

因为.css存在优先级问题,写在后面的样式会覆盖前面的样式,所以下载静态资源是最好是保证先后关系;笔者使用了Promise.all的方法一次性下载所有.CSS静态资源,并不能保证样式插入的先后顺序与原页面相同;

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