elment的表格设置宽度为100%之后打印还是不能将表格打印完整 如下图

 

1.寻找问题

为什么会出现这种情况,打开控制台查看代码

原来是el-table 会计算100%宽度为具体多少px 然后再计算出每一列的宽度 通过设置table>colgroup>col 的width属性来设置每一列的宽度。问题是浏览器的打印区域的100%的具体px如这里的1388px肯定与打印纸的宽度不一致 所以导致部分区域打印不出来

2.解决思路 那就把col这里的具体宽度设置成百分比就OK了。

        2.1首先看能不能从element 着手,但是element 的table有设置Table-column Attributes 的width属性 但是是px不是百分百。

        2.2既然element不行 那就从vue-print-nb 着手,首先 我们要清楚print的原理其实就是将我们要打印的id包裹的内容(其实是生成图片)放到一个iframe 然后再打印。那我们就走打印之前修改这些table>colgroup>col 属性的width 。来看看他的钩子回调函数

        结果是这些函数的回调都是在插入 iframe后才调用。都已经走到这里了 放弃是不可能的了,怎么办呢 ,那就看我们的第三步

3.修改源码。

首先我们要写一些样式覆盖原来的table的宽度样式 确保宽度不是一个具体的px

#printData {
		 ::v-deep .el-table {
			margin-top: 10px;
			table{
				width: 100%!important;
			}
			.el-table__body,
			.el-table__header {
				width: 100% !important;
			}

			.el-table__body {
				width: 100% !important;
			}

			
		}
	}

我们进入vue-print-nb的目录

 我们在main.js 中

import Print from 'vue-print-nb'

其实是用的lib下的文件 断点调试的时候跳进的是这个文件

 这个是压缩过的文件 要修改当然有一定难度 我们退而求其次,修改print文件夹下的文件

 主要就是print.js 和printarea.js 文件

其实也不用一行一行的研究代码,首先我们从钩子函数开始入手,随便复制一个钩子函数的名字进行搜索 (比如复制beforeOpenCallback )

 所以的钩子函数都在这里 那我们按照他的样式 添加一个钩子函数(beforeEntryIframe函数)

 new Print({
        ids: id, // * 局部打印必传入id
        vue,
        url: binding.value.url, // 打印指定的网址,这里不能跟id共存 如果共存id的优先级会比较高
        standard: '', // 文档类型,默认是html5,可选 html5,loose,strict
        extraHead: binding.value.extraHead, // 附加在head标签上的额外标签,使用逗号分隔
        extraCss: binding.value.extraCss, // 额外的css连接,多个逗号分开
        previewTitle: binding.value.previewTitle || '打印预览', // 打印预览的标题
        zIndex: binding.value.zIndex || 20002, // 预览窗口的z-index
        previewPrintBtnLabel: binding.value.previewPrintBtnLabel || '打印', // 打印预览的标题
        popTitle: binding.value.popTitle, // title的标题
        preview: binding.value.preview || false, // 是否启动预览模式
        asyncUrl: binding.value.asyncUrl,
        beforeEntryIframe(){
           binding.value.beforeEntryIframe && binding.value.beforeEntryIframe(vue)
        },
        previewBeforeOpenCallback () { // 预览窗口打开之前的callback
          binding.value.previewBeforeOpenCallback && binding.value.previewBeforeOpenCallback(vue)
        },
        previewOpenCallback () { // 预览窗口打开之后的callback
          binding.value.previewOpenCallback && binding.value.previewOpenCallback(vue)
        },
        openCallback () { // 调用打印之后的回调事件
          binding.value.openCallback && binding.value.openCallback(vue)
        },
        closeCallback () {
          binding.value.closeCallback && binding.value.closeCallback(vue)
        },
        beforeOpenCallback () {
          binding.value.beforeOpenCallback && binding.value.beforeOpenCallback(vue)
        }
      });

  printarea.js文件中会有调用这里的定义的回调函数,我们像中ifram插入内容之前修改,那就要走插入之前执行我们新加的钩子函数。

 printarea.js 文件一进来我们看到了一个init方法,在这里面打开预览前面有一个写入内容。这就很重要了 一定是要在写入内容前操作表格。果断进入这个write方法,

 这里我们应该是要操组ifram  body内的内容所以进入这里的getbody()方法

 getBody () {
    let ids = this.settings.ids;
    ids = ids.replace(new RegExp("#", "g"), '');
    this.settings.beforeEntryIframe();
    this.elsdom = this.beforeHanler(document.getElementById(ids));
    let ele = this.getFormData(this.elsdom);
    let htm = ele.outerHTML;
    return '<body>' + htm + '</body>';
  }

我们在这个方法中执行我们之前写的beforeEntryIframe钩子函数

当然最重要的是我们要去处理这个表格中的宽度未百分比的这个beforeEntryIframe 方法的具体实现

print: {
	id: 'printData',
	popTitle: '打印', // 打印配置页上方标题
	extraHead: '', //最上方的头部文字,附加在head标签上的额外标签,使用逗号分隔
	preview: '', // 是否启动预览模式,默认是false(开启预览模式,可以先预览后打印)
	previewTitle: '', // 打印预览的标题(开启预览模式后出现),
	previewPrintBtnLabel: '', // 打印预览的标题的下方按钮文本,点击可进入打印(开启预览模式后出现)
	zIndex: '', // 预览的窗口的z-index,默认是 20002(此值要高一些,这涉及到预览模式是否显示在最上面)
	previewBeforeOpenCallback() {}, //预览窗口打开之前的callback(开启预览模式调用)
	previewOpenCallback() {}, // 预览窗口打开之后的callback(开启预览模式调用)
	beforeEntryIframe() {
		const widthArr = ['25%', '10%', '15%', '50%'];
		const tables = document.getElementById('tablediv7').getElementsByTagName('table'); //获取打印的表格
		const headcolgroupCol = tables[0].getElementsByTagName('colgroup')[0].getElementsByTagName('col');
		const headcolgroupCol1 = tables[1].getElementsByTagName('colgroup')[0].getElementsByTagName('col');
		widthArr.forEach((val, index) => {
			headcolgroupCol[index].width = val;
			headcolgroupCol1[index].width = val;
		})
	},
	openCallback() {

	}, // 调用打印之后的回调事件
	closeCallback() {}, //关闭打印的回调事件(无法确定点击的是确认还是取消)
	url: '',
	standard: '',
	extraCss: '',
	loading: false,
},

        来看看效果

 结束!!!

特别注意,这里改为vue-print-nb 文件之后要把包中print文件复制出来 然后在main.js修改路径为复制之后的地址 这样确保我们引用的是自己修改的文件并且防止被人npm install 之后引用的还是官方的未改的包 同时可以npm unintall vue-print-nb 删除这个包了

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐