vue 浏览器 打印 vue-print-nb.js
备注: 由于本人是个后端,第一次搞前端打印功能,网上很多打印都是一些简单调用vue-print-nb的复制粘贴,没有太多详细的教程,经过摸索,结合多方查找知识点,终于依靠自己的“土方法”完成了需求,特此记录一下,希望对刚做打印功能的朋友们有帮助
npm install vue-print-nb --save
在main.js文件中注册:
import Print from 'vue-print-nb'
Vue.use(Print) // 浏览器打印插件
需求:点击打印按钮,预览打印的订单信息,打印一张A4纸,要求每页有26行表格,底部附带该订单的固定信息。同时支持多页打印。
初始效果:
先调试一页纸,调节好表行和底部固定信息的高度,使之刚好填充满一整页。对于超过26行的数据做代码逻辑分页。使用CSS(style="page-break-after: always;")可以进行强制html分页。对于未满26行的数据,通过计算26-真实数据个数得到空白行数;使用
占位填充。使用CSS(style="width: 0; height: 0; overflow: hidden
")来不占空间的先隐藏要打印的信息,这样通过打印按钮点击就可以打印了,浏览器会自动提供预览功能。
这里我根据自己的需求写成了一个vue打印组件print-order-info.vue
,然后使用组件实现需求;我采用了vue-print-nb的js配置方式来实现打印,过程遇到一个问题,每次点击绑定了v-print指令的按钮时,该按钮的点击事件还没来得及请求数据表格就已经被打印出来了。因此我的思路是 v-print打印指令 和 @click请求数据事件 不能放在同一个button按钮上,要用 一个显示“打印”的@click请求数据按钮 和 一个隐藏的v-print打印功能按钮;每次点击显示按钮时,先发起数据请求,数据请求返回成功后再使用document.getElementById('printButtonRef').click()
模拟按钮点击事件,进而触发被隐藏的v-print按钮的预览打印功能。
单元格内容过多导致单元格变形甚至整个页面的排版,超出部分使用省略号...
组件引入与使用:
print-order-info.vue
<template>
<!-- <el-dialog-->
<!-- title="打印票单"-->
<!-- :visible.sync="dialogVisible"-->
<!-- width="60%"-->
<!-- :before-close="handleClose">-->
<!-- 这里在调试的时候可以使用el-dialog包裹,使对话框一直可见;待调试完成后,将el-dialog去掉,改用下面的隐藏css样式标签包裹 -->
<!-- 这里是隐藏的html,用于打印票单时的界面效果 -->
<!-- style="width: 0; height: 0; overflow: hidden" 这里跟对话框二选一,上面的对话框是调试用的-->
<div style="width: 0; height: 0; overflow: hidden">
<div id="printMe">
<!-- 换页CSS,逻辑分页 -->
<div class="page" v-for="(page, pageIndex) in printData.pageArray" :key="'page' + pageIndex">
<table class="content-table">
<th class="base-cell">序号</th>
<th class="base-cell skuCode">商品编码</th>
<th class="base-cell skuName">商品名称</th>
<th class="base-cell weight">重量/斤</th>
<th class="base-cell binQty">料箱数</th>
<tr v-for="(row, dataIndex) in page" :key="row.skuCode">
<td class="center-cell">{{ pageIndex * pageSize + dataIndex + 1 }}</td>
<td class="center-cell skuCode text-ellipsis">{{ row.skuCode }}</td>
<td class="base-cell skuName text-ellipsis">{{ row.skuName }}</td>
<td class="center-cell weight text-ellipsis">{{ row.weight | weightFilter }}</td>
<td class="center-cell binQty text-ellipsis">{{ row.binQty || 0 }}</td>
<template v-if="pageIndex === printData.pageArray.length - 1">
<tr v-for="(blankRow, blankIndex) in blankRowNum" :key="'blank' + blankIndex">
<td class="center-cell" style="width: 50px;"> </td>
<td class="center-cell skuCode" style="width: 160px;"> </td>
<td class="base-cell skuName"> </td>
<td class="center-cell weight" style="width: 80px;"> </td>
<td class="center-cell binQty" style="width: 80px;"> </td>
</template>
</table>
<div style="margin: 5px 0"></div>
<table class="table-header">
<th class="base-cell">工单号</th>
<td class="center-cell text-ellipsis" style="width: 230px;">
<span v-if="printData.workOrderNO">{{ printData.workOrderNO }}</span>
<span v-else> </span>
<th class="base-cell" style="width: 155px;">生产用料清单号</th>
<td class="center-cell text-ellipsis" style="width: 260px;" colspan="2">
<span v-if="printData.voucherCode">{{ printData.voucherCode }}</span>
<span v-else> </span>
<tr class="multi-row">
<th class="base-cell">车间</th>
<td style="width: 645px;" class="center-cell" colspan="4">
<span v-if="printData.workShopName" class="moddle-text">{{ printData.workShopName }}</span>
<span v-else> </span>
<tr class="multi-row">
<th class="base-cell">楼层<br />备注</th>
<td style="width: 645px;" class="center-cell" colspan="4">
<span v-if="printData.floorRemark" class="moddle-text">{{ printData.floorRemark }}</span>
<span v-else> </span>
<tr class="multi-row">
<th class="base-cell">货号</th>
<td style="width: 385px;" class="center-cell" colspan="2">
<span v-if="printData.productName" class="big-text">{{ printData.productName }}</span>
<span v-else> </span>
<th class="base-cell" style="width: 130px">
料箱<br />总数
<td class="center-cell" style="width: 130px;">
<span v-if="printData.totalBinQty" class="small-text">{{ printData.totalBinQty }}</span>
<span v-else> </span>
</table>
</div>
</div>
<button
id="printButtonRef"
v-print="printObj">
</button>
</div>
<!-- </el-dialog>-->
</div>
</template>
<script>
import { keepTwoDecimal } from '@/utils/unit'
export default {
name: 'PrintOrderInfo',
data() {
return {
pageSize: 26, // 每页总行数
// 控制对话框显示与隐藏
dialogVisible: false,
printObj: { // 打印配置对象
id: 'printMe',
popTitle: ' ',
extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>'
// 打印表单数据对象
printData: {
pageArray: [], // 分页数据(二维数组)
workShopName: '', // 车间
voucherCode: '', // 生产用料清单号
workOrderNO: '', // 工单号
floorRemark: '', // 楼层备注
productName: '', // 货号
totalBinQty: '' // 料箱总数
filters: {
weightFilter(weight) {
return weight ? keepTwoDecimal(weight) : 0
computed: {
// 打印票单的空白行数
blankRowNum() {
const { pageArray } = this.printData
if (pageArray && pageArray.length) {
const pageTotal = pageArray.length
const lastPage = pageArray[pageTotal - 1]
return this.pageSize - lastPage.length
return 0
methods: {
// 显示上架绑定dialog
open(printData) {
this.dialogVisible = true
// 本地mock测试数据(仅用于样式的调试和自测)
// printData = {
// workShopName: 'aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddddeeeeeeeeeeeeeeeeeeffffffffffffffffffffffgggggggggggggggggggggggggghhhhhhhhhhhhhhhhhhhhhh',
// voucherCode: 'jii234-ffhrhfttjefeggegejgegggegegrtuuiiewrtcbnkl',
// workOrderNO: 'adsdafejfiejgoejiogijegijekgjekjgegegegeegeoijngefef',
// floorRemark: '天空那么高!一片片薄纱似的白云在慢慢地浮动着,对我说:你看天空那么高!一片片薄纱似的白云在慢慢地浮动着,对我说:你看天空那么高!一片片薄纱似的白云在慢慢地浮动着,对我说:你看天空那么高!一片片薄纱似的白云在慢慢地浮动着,对我说:你看',
// productName: 'crd000311crd000311crd000311crd000311crd000311crd000311crd000311',
// totalBinQty: '123456789787984884552259658542665895422658855',
// orderDetails: [{
// skuCode: '04.070.25.011',
// skuName: '中蓝机甲身(牙白身中蓝臂)',
// weight: '2.1740000',
// binQty: 1
// }]
this.initData(printData)
// 触发隐藏的打印按钮点击事件,开始打印票单
document.getElementById('printButtonRef').click()
// 关闭对话框事件
handleClose() {
this.dialogVisible = false
// 初始化数据
initData(printData) {
const {
orderDetails, // 表格数据
workShopName, // 车间
voucherCode, // 生产用料清单号
workOrderNO, // 工单号
floorRemark, // 楼层备注
productName, // 货号
totalBinQty // 料箱总数
} = printData
// 一维数组拆分成二维数组(代码逻辑数据分页)
const pageArray = []
const total = orderDetails.length
const pageNum = Math.ceil(total / this.pageSize)
for (let i = 0; i < pageNum; i++) {
const pageArr = []
if (i === pageNum - 1) {
pageArray.push(orderDetails)
} else {
for (let j = 0; j < this.pageSize; j++) {
pageArr.push(orderDetails.shift())
pageArray.push(pageArr)
this.printData = {
pageArray, // 分页数据
workShopName, // 车间
voucherCode, // 生产用料清单号
workOrderNO, // 工单号
floorRemark, // 楼层备注
productName, // 货号
totalBinQty // 料箱总数
</script>
<style lang="scss" scoped>
.page {
page-break-after: always;
table {
table-layout: fixed;
border: 1px solid black;
width: 100%;
margin: 0 auto;
border-spacing: 0;
border-collapse: collapse;
font-size: 20px;
.content-table {
.skuCode {
width: 160px;
.skuName {
width: 350px;
.weight {
width: 80px;
.binQty {
width: 80px;
.base-cell {
border: 1px solid black;
.center-cell {
border: 1px solid black;
text-align: center;
.table-header {
font-size: 20px;
line-height: 25px;
.big-text {
font-size: 40px;
font-weight: 700;
line-height: 45px;
overflow: hidden; // 超出隐藏
text-overflow: ellipsis; //溢出显示省略号
white-space: normal; //常规默认,会折行
display: -webkit-box;
-webkit-box-orient: vertical; //子元素排列 vertical(竖排)orhorizontal(横排)
-webkit-line-clamp: 2;/*内容限制的行数 需要几行写几就行*/
border: none; // 隐藏自身边框
word-break: break-all; // 对字母也换行
.moddle-text {
font-size: 27px;
line-height: 33px;
overflow: hidden; // 超出隐藏
text-overflow: ellipsis; //溢出显示省略号
white-space: normal; //常规默认,会折行
display: -webkit-box;
-webkit-box-orient: vertical; //子元素排列 vertical(竖排)orhorizontal(横排)
-webkit-line-clamp: 3;/*内容限制的行数 需要几行写几就行*/
border: none; // 隐藏自身边框
word-break: break-all; // 对字母也换行
.small-text {
overflow: hidden; // 超出隐藏
text-overflow: ellipsis; //溢出显示省略号
white-space: normal; //常规默认,会折行
display: -webkit-box;
-webkit-box-orient: vertical; //子元素排列 vertical(竖排)orhorizontal(横排)
-webkit-line-clamp: 4;/*内容限制的行数 需要几行写几就行*/
border: none; // 隐藏自身边框
word-break: break-all; // 对字母也换行
.multi-row {
height: 100px;
.text-ellipsis{
overflow:hidden;
white-space: nowrap;
text-overflow: ellipsis;
-o-text-overflow:ellipsis;
</style>
代码优化后预览效果
实际打印效果:(一页调试时的效果)
完结番!