演示
提示:
1.打印无刷新返回可用于任何框架包括原生JS
2.打印保持输入的值,支持input、textarea、select、单选框、复选框
3.打印保持输入的值,默认支持iview与element-ui的dom结构(其他的UI库还没测试过,只要DOM结构与iview和element-ui一样那就可以使用),如要支持自己定义的DOM结构需要注释以下代码
4.打印不支持css的:after,所以要在打印函数里自定义单复选框的样式。代码同上2张图片。如样式没特殊需求可以不修改以上代码
5.doc.querySelector('#app');body下最顶级的元素,按自己项目的id或class修改。如图
6.最好不要有跟#app平级的元素。如果必须要有平级的元素,需要保存跟#app同级的所有元素
JS代码
/**
* @description 打印返回免刷新
* 提示:
* 1、如果只需要打印表格可以把用/**------**\/划分的代码注释,避免浪费性能
* 2、最好不要有跟#app平级的元素。如果必须要有平级的元素,需要保存跟#app同级的所有元素
* @param {String} printTarget - 打印范围的元素
**/
export function printing({printTarget}) {
let textareaArr = [];
let inputArr = {};
let checkedArr = {};
let radioArr = {};
let doc = document;
let body = doc.body;
let app = doc.querySelector('#app'); // body下最顶级的元素
/**
* 如果使用router.addRoutes创建的路由和动态菜单,打印后不显示菜单栏
* 需要保存菜单的dom,并放开最后一行代码的注释
**/
// let menu = doc.querySelector('.el-menu--vertical'); // .el-menu--vertical 菜单元素的class,按自己元素的class来填写
let contentPrint = doc.querySelector(`${printTarget}`); // 要打印的范围
/**------------------------------------------------------------------------------------------------------**/
let input = contentPrint.querySelectorAll('input'); // 获取input框
// 获取input值
for (let i = 0; i < input.length; i++) {
if (input[i].type === 'text') {
inputArr[i] = input[i].value
} else if (input[i].type === 'checkbox') {
checkedArr[i] = input[i].checked
} else if (input[i].type === 'radio') {
radioArr[i] = input[i].checked
}
}
let textarea = contentPrint.querySelectorAll('textarea'); // 获取textarea框
// 获取textarea值
for (let item of textarea) {
textareaArr.push(item.value)
}
/**------------------------------------------------------------------------------------------------------**/
/**
* 不可注释
**/
contentPrint.classList.add('content-printing'); // 添加class以区分相同的class
body.removeChild(app); // 移除body下最顶级的元素
body.innerHTML = contentPrint.parentElement.innerHTML; // 覆盖全部body内的内容
body.style.cssText += 'display: flex;justify-content: center;'; // 居中打印
/**------------------------------------------------------------------------------------------------------**/
let printInput = doc.querySelectorAll('.content-printing input'); // 获取dom改变后的input框
// input赋值
for (let i = 0; i < printInput.length; i++) {
if (printInput[i].type === 'text') {
printInput[i].value = inputArr[i];
} else if (printInput[i].type === 'checkbox') {
printInput[i].checked = checkedArr[i];
// 复选框样式
printInput[i].previousElementSibling.style.display = 'none';
printInput[i].style.cssText += 'width: 14px;\n' +
' height: 14px;\n' +
' position: static;\n' +
' z-index: auto;\n' +
' opacity: 1;'
} else if (printInput[i].type === 'radio') {
printInput[i].checked = radioArr[i];
// 单选框样式
printInput[i].previousElementSibling.style.display = 'none';
printInput[i].style.cssText += ' position: static;\n' +
' opacity:1;'
}
}
let printTextarea = doc.querySelectorAll('.content-printing textarea'); // 获取dom改变后的textarea
// textarea赋值
for (let i = 0; i < printTextarea.length; i++) {
printTextarea[i].value = textareaArr[i];
}
/**------------------------------------------------------------------------------------------------------**/
// 打印
window.print();
body.style.cssText = '';
doc.querySelector('.content-printing').remove(); // 打印或取消后移除打印内容
body.appendChild(app); // 添加回body下最顶级的元素
/**
* 放开这一行的注释,添加回菜单
**/
// if (menu) {
// body.appendChild(menu);
// }
}
VUE 调用
<template>
<!-- <el-dialog-->
<!-- title="打印"-->
<!-- :visible.sync="bool"-->
<!-- width="30%"-->
<!-- :before-close="close">-->
<Modal v-model="bool" @on-cancel="close" title="打印" :transfer="false">
<div class="print">
<h1>iview</h1>
<Input v-model="value" placeholder="Enter something..."/>
<RadioGroup v-model="animal">
<Radio label="金斑蝶"></Radio>
<Radio label="爪哇犀牛"></Radio>
<Radio label="印度黑羚"></Radio>
</RadioGroup>
<CheckboxGroup v-model="social">
<Checkbox label="twitter">
<Icon type="logo-twitter"></Icon>
<span>Twitter</span>
</Checkbox>
<Checkbox label="facebook">
<Icon type="logo-facebook"></Icon>
<span>Facebook</span>
</Checkbox>
<Checkbox label="github">
<Icon type="logo-github"></Icon>
<span>Github</span>
</Checkbox>
<Checkbox label="snapchat">
<Icon type="logo-snapchat"></Icon>
<span>Snapchat</span>
</Checkbox>
</CheckboxGroup>
<Input v-model="value16" maxlength="100" show-word-limit type="textarea" placeholder="Enter something..." style="width: 200px" />
<Select v-model="model1" style="width:200px">
<Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option>
</Select>
<h1>element-ui</h1>
<el-select v-model="selectValue" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-input v-model="input" placeholder="请输入内容"></el-input>
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
placeholder="请输入内容"
v-model="textarea2">
</el-input>
<el-radio-group v-model="radio">
<el-radio :label="3">备选项</el-radio>
<el-radio :label="6">备选项</el-radio>
<el-radio :label="9">备选项</el-radio>
</el-radio-group>
<el-checkbox-group v-model="checkList">
<el-checkbox label="复选框 A"></el-checkbox>
<el-checkbox label="复选框 B"></el-checkbox>
<el-checkbox label="复选框 C"></el-checkbox>
</el-checkbox-group>
<!-- <h1>自定义DOM结构</h1>-->
<!-- <div>-->
<!-- <input type="radio" name="sex" value="male">Male-->
<!-- <input type="radio" name="sex" value="female">Female-->
<!-- </div>-->
</div>
<template slot="footer">
<div>
<Button @click="print">打印</Button>
</div>
</template>
</Modal>
<!-- </el-dialog>-->
</template>
<script>
import {printing} from './js/print'
export default {
name: "modal-print",
props: {
isShow: Boolean
},
data() {
return {
checkList: [],
radio:'',
textarea2:'',
input:'',
options: [{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶'
}, {
value: '选项3',
label: '蚵仔煎'
}, {
value: '选项4',
label: '龙须面'
}, {
value: '选项5',
label: '北京烤鸭'
}],
selectValue: '',
bool: false,
value: '',
animal: '',
social: [],
value16: '',
cityList: [
{
value: 'New York',
label: 'New York'
},
{
value: 'London',
label: 'London'
},
{
value: 'Sydney',
label: 'Sydney'
},
{
value: 'Ottawa',
label: 'Ottawa'
},
{
value: 'Paris',
label: 'Paris'
},
{
value: 'Canberra',
label: 'Canberra'
}
],
model1: ''
}
},
watch: {
isShow(val) {
this.bool = val
}
},
methods: {
print() {
printing({printTarget: '.print'})
},
close() {
this.$emit('close')
}
}
}
</script>