打印

js调起打印(某个div里的内容)

vue + elementUI

  • vue
<template>
<div id="printBox">
        打印的内容
        <el-button class="noprint" @click="printing" type="primary">打印</el-button>
</div>
</template>
  • js
       printing () {
            var body=document.getElementById("printBox"); // 获取打印部分的div
            document.body.outerHTML=body.outerHTML // 打印div中的内容  outerHTML => 打印可以带上css样式
            window.print(); // js调起打印
            location.reload(); // 打印完成后,或取消打印,复原页面内容,直接刷新
        }
  • css(打印时的样式,隐藏掉打印按钮)
<style>
@media print {
        .noprint{
            display: none;
        }
    }
</style>

打印时打开一个新页面,打印后关闭

  • html
 <div id="printBox"> 
        <!--你需要打印的内容-->
 </div>
  • js
var printBox = document.getElementById('printBox'); //获取需要打印的内容
var newWin = window.open(window.document.URL); //新打开一个标签页,这样不会影响现使用的页面
var newContent =printBox.innerHTML;
newWin.document.body.innerHTML = newContent; //将打印的部分赋值给新打开的标签页
newWin.print();//执行打印
newWin.close();//关闭打印窗口

https://blog.csdn.net/wwwwerewrew/article/details/100137746

A4纸打印

@media print { // 打印时执行
        @page { // 设置打印样式
            size: A4; // A4
            size: portrait; // 纵向打印
            margin: 0; // 边距设置,自定义
        }
        // 隐藏滚动条
        ::-webkit-scrollbar {display:none} 
    }

https://www.softwhy.com/article-5613-1.html

  • 打印的背景颜色不展示
-webkit-print-color-adjust: exact; // 加给打印的div即可

https://www.cnblogs.com/sese/p/9057732.html

Safari 兼容

插件:https://www.cnblogs.com/coderwhytop/p/14462603.html

问题1:Safari打印一次后,不能再次打印

原因:document.body.removeChild(frame1) 删除元素太快
解决办法:加setTimeout,延时处理
前提:使用print.js打印
https://cloud.tencent.com/developer/ask/208425

问题2:Safari 按794px×1123px写的页面,打印A4纸,一小部分不展示

临时解决办法:判断Mac系统,给打印的部分做了缩放

使用流程:

1、main.js

import Print from '@/utils/print.js' // 打印
Vue.use(Print)

2、js 调用打印

   let body = document.getElementById("print");
   document.body.outerHTML = body.outerHTML
   that.$print(that.$refs.print)

3、css(为了修复问题2,看情况使用,仅供参考)

  • 动态加class
<div :class="isMac? 'is_mac': ''"></div>
  • css只针对Mac缩放
    .is_mac {
          transform: scale(0.97);  // 缩放比例
          transform-origin: 0 bottom; // 缩放位置
    }
  • js判断系统是否是Mac
data() {
   return {
          isMac: false
   }
},
created() {
      this.isMac = /macintosh|mac os x/i.test(navigator.userAgent)
}

https://blog.csdn.net/jingtian678/article/details/86378694/

4、修改后的插件 utils/print.js

// 打印类属性、方法定义
/* 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')
                        }
                    }
                }
            }
        }

        let outerHTML = this.wrapperRefDom(this.dom).outerHTML
        return outerHTML;
    },
    // 向父级元素循环,包裹当前需要打印的元素
    // 防止根级别开头的 css 选择器不生效
    wrapperRefDom: function(refDom) {
        let prevDom = null
        let currDom = refDom
            // 判断当前元素是否在 body 中,不在文档中则直接返回该节点
        if (!this.isInBody(currDom)) return currDom

        while (currDom) {
            if (prevDom) {
                let element = currDom.cloneNode(false)
                element.appendChild(prevDom)
                prevDom = element
            } else {
                prevDom = currDom.cloneNode(true)
            }

            currDom = currDom.parentElement
        }

        return prevDom
    },
    writeIframe: function(content) {
        var _this = this
        if (/macintosh|mac os x/i.test(navigator.userAgent) || navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1) { // Mac或企业微信
            var frame = this.appendFrame(content);
            _this.macPrint(frame)
        } else {
            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();
            iframe.onload = function() {
                _this.toPrint(w);
                setTimeout(function() {
                    document.body.removeChild(iframe)
                }, 100)
            }
        }
    },
    // mac 创建打印元素
    appendFrame: function(content) {
        var frame1 = document.createElement('iframe');
        frame1.name = "frame3";
        frame1.style.position = "absolute";
        frame1.style.top = "-1000000px";
        document.body.appendChild(frame1);

        var frameDoc = frame1.contentWindow ? frame1.contentWindow : frame1.contentDocument.document ? frame1.contentDocument.document : frame1.contentDocument;
        frameDoc.document.open();
        frameDoc.document.write(content);
        frameDoc.document.close();

        return frame1;
    },

    toPrint: function(frameWindow) {
        try {
            setTimeout(function() {
                frameWindow.focus();
                try {
                    if (!frameWindow.document.execCommand('print', false, null)) {
                        frameWindow.print();
                        location.reload(); // 刷新页面
                    }
                } catch (e) {
                    frameWindow.print();
                    location.reload(); // 刷新页面
                }
                frameWindow.close();
                location.reload(); // 刷新页面
            }, 10);
        } catch (err) {
            console.log('err', err);
        }
    },
    // Safari打印兼容
    macPrint: function(frame) {
        // Safari
        if (!window.onafterprint) {
            // emulate onbeforeprint/onafterprint events
            var mediaQueryCallback = function(mql) {
                if (!mql.matches && frame) {
                    setTimeout(function() { // 延时,解决打印自动关闭问题
                        document.body.removeChild(frame);
                        location.reload(); // 刷新页面
                    }, 200)
                }
            };
            var mediaQueryList = window.frames[frame.name].matchMedia('print');
            mediaQueryList.addListener(mediaQueryCallback);

            // the code below will trigger a cleanup in case a user hits Cancel button
            // in that Safari's new additional print confirmation dialog
            window.frames[frame.name].focus();
            window.frames[frame.name].onfocus = function() {
                return mediaQueryCallback(mediaQueryList);
            };
        }

        window.frames[frame.name].print();

        return false;
    },
    // 检查一个元素是否是 body 元素的后代元素且非 body 元素本身
    isInBody: function(node) {
        return (node === document.body) ? false : document.body.contains(node);
    },
    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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • JS实现打印的方式 方式一:window.print() 方式二:使用html 标签 引入Webbrowser控件...
    技术与健康阅读 4,800评论 0 7
  • 一、概念介绍 Vue.js和React.js分别是目前国内和国外最火的前端框架,框架跟类库/插件不同,框架是一套完...
    刘远舟阅读 953评论 0 0
  • 技术点: 不定期更新补充 页面引用svg symbol标签创建icon p:nth-child(2) 与 p:nt...
    wwmin_阅读 1,378评论 0 52
  • 前言 接触vue框架也有一个多月的时间了,整理下之前做过的一个小demo,主要是熟悉vue全家桶技术,界面布局模仿...
    视觉派Pie阅读 26,381评论 20 285
  • Nuxt爬坑 第一节:nuxt.js相关概述 nuxt.js简单的说是Vue.js的通用框架,最常用的就是用来作S...
    阿_军阅读 945评论 0 0