原生js打印功能

/**
 * 声明Symbol的变量是为了设置类的私有方法或者变量
 */
const IFRAME = Symbol('iframe');
const LINK_LIST = Symbol('linkList');

const INIT = Symbol('init');
const GET_LINK = Symbol('getLink');
const GET_DOM = Symbol('getDOM');
const ADD_EVENT = Symbol('addEvent');
const CREATE_IFRAM = Symbol('createIframe');
const CREATE_LINK = Symbol('createLink');
const CREATE_CONTENT = Symbol('createContent');

/**
 * @description: 打印文档中的特定区域
 * @param {string || object} eventSource 事件源(触发事件的源)
 * @param {string || object} target 目标源(打印内容)
 * @param {string} title 打印标题
 * @param {string} args 打印需要的样式文件
 * 注意:除了前两个参数,剩余的都为样式文件,即link标签中的href路径
 */
class PrintSpecificPartOfDoc {
    constructor(eventSource, target, title, ...args) {
        this.eventSource = this[GET_DOM](eventSource);
        this.target = this[GET_DOM](target);
        this.title = title;

        this[IFRAME] = null;
        this[LINK_LIST] = [];

        args.forEach(href => {
            let link = document.createElement('link');
            link.setAttribute('href', href);
            this[LINK_LIST].push(link);
        })

        this[ADD_EVENT](this.eventSource, 'click', () => {
            this[INIT]();
        })
    };
    /**
     * @description: 初始化事件
     */    
    [INIT]() {
        this[CREATE_IFRAM]();
        this[CREATE_LINK]();
        this[CREATE_CONTENT]();
        /**
         * 添加延时器的目的:为了解决首次打印的时候,样式未加载完成的时候,就已经触发打印事件
         */
        setTimeout(() => {
            this[IFRAME].contentWindow.print();
        }, 50)
    };
    /**
     * @description: 创建iframe标签
     */    
    [CREATE_IFRAM]() {
        // 判断iframe标签是否存在是为了避免多次创建影响性能
        if (!this[IFRAME]) {
            let iframe = document.createElement('iframe');
            iframe.setAttribute('id', 'printIframe');
            iframe.style.display = 'none';
            document.body.appendChild(iframe);
        }
    };
    /**
     * @description: 创建打印需要的样式
     */    
    [CREATE_LINK]() {
        this[IFRAME] = document.getElementById('printIframe');

        let styleSheets = [...this[LINK_LIST], ...this[GET_LINK]()];

        let doc = this[IFRAME].contentWindow.document;
        let head = doc.getElementsByTagName('head')[0];

        let title = document.createElement('title');
        title.innerHTML = this.title;
        head.appendChild(title);

        styleSheets.forEach(styleSheet => {
            head.appendChild(styleSheet);
        })
    };
    /**
     * @description: 创建打印的内容区域
     */    
    [CREATE_CONTENT]() {
        let doc = this[IFRAME].contentWindow.document;
        let body = doc.querySelector('body');

        body.innerHTML = '';
        body.appendChild(this.target.cloneNode(true));
    };
    /**
     * @description: 获取打印的样式
     */
    [GET_LINK]() {
        const styles = document.getElementsByTagName('head')[0].getElementsByTagName('link');
        let printCss = [];
        for (let i = 0; i < styles.length; i++) {
            let attr = styles[i].getAttribute('media');
            if (attr == 'all' || attr == 'print') printCss.push(styles[i].cloneNode(true));
        }
        return printCss;
    };
    /**
     * @description: 获取DOM
     * @param {string || object} el domID || DOM
     * @return {object} dom对象
     */
    [GET_DOM](el) {
        if (typeof el !== 'string' && typeof el !== 'object') {
            throw new TypeError(`The "${el}" is not a String or Object!`);
        }

        return typeof el === 'string' ? document.getElementById(el) : el;
    };
    /**
     * @description: 添加事件
     * @param {object} node DOM节点
     * @param {string} type 事件类型
     * @param {function} fn 事件回调
     */
    [ADD_EVENT](node, type, fn) {
        if (node.addEventListener) {
            node.addEventListener(type, fn, false);
        } else if (node.attachEvent) {
            node.attachEvent('on' + type, function () {
                fn.call(node, window.event);
            })
        }
    };
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值