js实现无刷新局部打印

840 阅读1分钟

演示

16825590-bd2982bfc2f2bfae.gif

提示:

1.打印无刷新返回可用于任何框架包括原生JS

2.打印保持输入的值,支持input、textarea、select、单选框、复选框

3.打印保持输入的值,默认支持iview与element-ui的dom结构(其他的UI库还没测试过,只要DOM结构与iview和element-ui一样那就可以使用),如要支持自己定义的DOM结构需要注释以下代码 1.png

2.png

4.打印不支持css的:after,所以要在打印函数里自定义单复选框的样式。代码同上2张图片。如样式没特殊需求可以不修改以上代码

5.doc.querySelector('#app');body下最顶级的元素,按自己项目的id或class修改。如图 3.png 4.png

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>