Vue uses print.js to implement printing components

First: Create the print.js file code under the common folder as follows

// 打印类属性、方法定义
/* eslint-disable */
const Print = function (dom, options) {
    
    
    if (!(this instanceof Print)) return new Print(dom, options);

    this.options = this.extend({
    
    
        'noPrint': '.no-print'
    }, options);

    if ((typeof dom) === "string") {
    
    
        this.dom = document.querySelector(dom);
    } else {
    
    
        this.isDOM(dom)
        this.dom = this.isDOM(dom) ? dom : dom.$el;
    }

    this.init();
};
Print.prototype = {
    
    
    init: function () {
    
    
        var content = this.getStyle() + this.getHtml();
        this.writeIframe(content);
    },
    extend: function (obj, obj2) {
    
    
        for (var k in obj2) {
    
    
            obj[k] = obj2[k];
        }
        return obj;
    },

    getStyle: function () {
    
    
        var str = "",
            styles = document.querySelectorAll('style,link');
        for (var i = 0; i < styles.length; i++) {
    
    
            str += styles[i].outerHTML;
        }
        str += "<style>" + (this.options.noPrint ? this.options.noPrint : '.no-print') + "{display:none;}</style>";

        return str;
    },

    getHtml: function () {
    
    
        var inputs = document.querySelectorAll('input');
        var textareas = document.querySelectorAll('textarea');
        var selects = document.querySelectorAll('select');

        for (var k = 0; k < inputs.length; k++) {
    
    
            if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {
    
    
                if (inputs[k].checked == true) {
    
    
                    inputs[k].setAttribute('checked', "checked")
                } else {
    
    
                    inputs[k].removeAttribute('checked')
                }
            } else if (inputs[k].type == "text") {
    
    
                inputs[k].setAttribute('value', inputs[k].value)
            } else {
    
    
                inputs[k].setAttribute('value', inputs[k].value)
            }
        }

        for (var k2 = 0; k2 < textareas.length; k2++) {
    
    
            if (textareas[k2].type == 'textarea') {
    
    
                textareas[k2].innerHTML = textareas[k2].value
            }
        }

        for (var k3 = 0; k3 < selects.length; k3++) {
    
    
            if (selects[k3].type == 'select-one') {
    
    
                var child = selects[k3].children;
                for (var i in child) {
    
    
                    if (child[i].tagName == 'OPTION') {
    
    
                        if (child[i].selected == true) {
    
    
                            child[i].setAttribute('selected', "selected")
                        } else {
    
    
                            child[i].removeAttribute('selected')
                        }
                    }
                }
            }
        }

        return this.dom.outerHTML;
    },

    writeIframe: function (content) {
    
    
        var w, doc, iframe = document.createElement('iframe'),
            f = document.body.appendChild(iframe);
        iframe.id = "myIframe";
        //iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
        iframe.setAttribute('style', 'position:absolute;width:0;height:0;top:-10px;left:-10px;');
        w = f.contentWindow || f.contentDocument;
        doc = f.contentDocument || f.contentWindow.document;
        doc.open();
        doc.write(content);
        doc.close();
        var _this = this
        iframe.onload = function(){
    
    
            _this.toPrint(w);
            setTimeout(function () {
    
    
                document.body.removeChild(iframe)
            }, 100)
        }
    },

    toPrint: function (frameWindow) {
    
    
        try {
    
    
            setTimeout(function () {
    
    
                frameWindow.focus();
                try {
    
    
                    if (!frameWindow.document.execCommand('print', false, null)) {
    
    
                        frameWindow.print();
                    }
                } catch (e) {
    
    
                    frameWindow.print();
                }
                frameWindow.close();
            }, 10);
        } catch (err) {
    
    
            console.log('err', err);
        }
    },
    isDOM: (typeof HTMLElement === 'object') ?
        function (obj) {
    
    
            return obj instanceof HTMLElement;
        } :
        function (obj) {
    
    
            return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
        }
};
const MyPlugin = {
    
    }
MyPlugin.install = function (Vue, options) {
    
    
    // 4. 添加实例方法
    Vue.prototype.$print = Print
}
export default MyPlugin

Register the module in main.js

// 打印
import print from '@/common/print'
Vue.use(print)

Create the component Print.vue that needs to be printed, introduce the component in the parent component, and register

// 引入
import print from './Print'
// 注册
components:{
    
    productionTaskListDetail,print},

The basic layout of the parent component (that is, the component that triggers the event)

<!--触发事件按钮-->
<el-button type="primary" icon="el-icon-printer" circle size="mini" plain @click="printerView(scope.row)"></el-button>

<!--打印的页面-->
<section ref="printer" >
    <print @changeData='changeData' :printId="printId" class="printer"></print>
</section>

Call the print method

printerView(val) {
    
    
	this.$print(this.$refs.printer)
},

Add a media query style to the printed page (view hidden component sets this style)

<style scoped>
    @media screen  {
    
    
        .printer {
    
    
            display: none;
        }
    }
</style>

Usage note: If the component needs the value of the parent component, the following logic can be used. If the component to be printed has a picture, the picture may not be displayed during the print preview. The solution is to pass a parameter printerId to the parent component after the picture is loaded. The printerId here is also the data passed by the parent component to the child component, and the parent component receives the printerId And print when printerId is not empty

// 给子组件传id
 printerView(val) {
    
    
     this.printId = val.id;
 },
// 判断子组件传过来的id,如果不为空证明子组件已经渲染结束
changeData(data) {
    
    
    if(!!data) {
    
    
        this.$print(this.$refs.printer)
        this.printId = ''
    }
}
// 图片渲染成功给父组件传递参数
<div class="image">
            <el-image @load="function(e) {
    
    
              $emit('changeData',printerId)
            }" class="image-possion" style="width: 150px; height: 150px" :src="`/rebar/base/downQr/?key=SCRUD&id=${
      
      headerData.id}`"></el-image>
        </div>

Guess you like

Origin blog.csdn.net/weixin_44640323/article/details/109331403