最优雅的方法

感谢评论区大佬netzhouxiang_提供的方法

declare module 'vue-print-nb';

问题

vue项目改造成对typescript支持的项目后,vue-print-nb打印指令无法使用
尝试有没有对应的typescript包,发现没有

解决办法

node_modules目录下找到vue-print-nb,复制出src/packages目录下的print.js和printarea.js。
把他们后缀改成ts,然后内部的类型处理一下。

print.ts

import Print from './printarea';
import Vue from "vue";Vue.directive("print", {inserted: function (el, binding, vnode) {let vue: any = vnode.context;let closeBtn = true;let id = '';el.addEventListener('click', () => {vue.$nextTick(() => {if (typeof binding.value === 'string') {id = binding.value;} else if (typeof binding.value === 'object' && !!binding.value.id) {id = binding.value.id;let ids = id.replace(new RegExp("#", "g"), '');let elsdom = document.getElementById(ids);if (!elsdom) console.log("id in Error"), id = '';}// 局部打印if (id) {localPrint();} else {// 直接全局打印window.print();}});});const localPrint = () => {if (closeBtn) {closeBtn = false;new Print({ids: id, // * 局部打印必传入idstandard: '', // 文档类型,默认是html5,可选 html5,loose,strictextraHead: binding.value.extraHead, // 附加在head标签上的额外标签,使用逗号分隔extraCss: binding.value.extraCss, // 额外的css连接,多个逗号分开popTitle: binding.value.popTitle, // title的标题endCallback() { // 调用打印之后的回调事件closeBtn = true;}});}};}
});

printarea.ts

export default class {constructor(option: any) {let that: any = this;that.standards = {strict: 'strict',loose: 'loose',html5: 'html5'};that.selectArray = []; // 存储select的that.counter = 0;that.settings = {standard: that.standards.html5,extraHead: '', // 附加在head标签上的额外元素,使用逗号分隔extraCss: '', // 额外的css逗号分隔popTitle: '', // 标题endCallback: null, // 成功打开后的回调函数ids: '' // 局部打印的id};Object.assign(that.settings, option);that.init();}init() {let that: any = this;that.counter++;that.settings.id = `printArea_${that.counter}`;let PrintAreaWindow = that.getPrintWindow(); // 创建iframethat.write(PrintAreaWindow.doc); // 写入内容that.print(PrintAreaWindow);that.settings.endCallback();}print(PAWindow: any) {let that: any = this;let paWindow = PAWindow.win;const _loaded = () => {paWindow.focus();paWindow.print();try {let box: any = document.getElementById(that.settings.id);let canvasList: any = that.elsdom.querySelectorAll('.canvasImg')console.log(that.elsdom)for (let i = 0; i < canvasList.length; i++) {let _parent = canvasList[i].parentNode_parent.removeChild(canvasList[i])}box.parentNode.removeChild(box);} catch (e) {console.log(e);}};if (window.ActiveXObject) {paWindow.onload = _loaded();return false;}paWindow.onload = () => {_loaded();};}write(PADocument: any, $ele: any) {let that: any = this;PADocument.open();PADocument.write(`${that.docType()}<html>${that.getHead()}${that.getBody()}</html>`);PADocument.close();}docType() {let that: any = this;if (that.settings.standard === that.standards.html5) {return '<!DOCTYPE html>';}var transitional = that.settings.standard === that.standards.loose ? ' Transitional' : '';var dtd = that.settings.standard === that.standards.loose ? 'loose' : 'strict';return `<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01${transitional}//EN" "http://www.w3.org/TR/html4/${dtd}.dtd">`;}getHead() {let that: any = this;let extraHead = '';let links = '';let style = '';if (that.settings.extraHead) {that.settings.extraHead.replace(/([^,]+)/g, (m: any) => {extraHead += m;});}// 复制所有link标签[].forEach.call(document.querySelectorAll('link'), function (item: any, i) {if (item.href.indexOf('.css') >= 0) {links += `<link type="text/css" rel="stylesheet" href="${item.href}" >`;}});// 循环获取style标签的样式let domStyle = document.styleSheets;if (domStyle && domStyle.length > 0) {for (let i = 0; i < domStyle.length; i++) {try {if (domStyle[i].cssRules || domStyle[i].rules) {let rules = domStyle[i].cssRules || domStyle[i].rules;for (let b = 0; b < rules.length; b++) {style += rules[b].cssText;}}} catch (e) {console.log(domStyle[i].href + e);}}}if (that.settings.extraCss) {that.settings.extraCss.replace(/([^,\s]+)/g, (m: any) => {links += `<link type="text/css" rel="stylesheet" href="${m}">`;});}return `<head><title>${that.settings.popTitle}</title>${extraHead}${links}<style type="text/css">${style}</style></head>`;}getBody() {let that: any = this;let ids = that.settings.ids;ids = ids.replace(new RegExp("#", "g"), '');that.elsdom = that.beforeHanler(document.getElementById(ids));let ele = that.getFormData(that.elsdom);let htm = ele.outerHTML;return '<body>' + htm + '</body>';}// 克隆节点之前做的操作beforeHanler(elsdom: any) {let canvasList = elsdom.querySelectorAll('canvas');// canvas转换png图片for (let i = 0; i < canvasList.length; i++) {if (!canvasList[i].style.display) {let _parent = canvasList[i].parentNodelet _canvasUrl = canvasList[i].toDataURL('image/png')let _img = new Image()_img.className = 'canvasImg'_img.style.display = 'none'_img.src = _canvasUrl// _parent.replaceChild(_img, canvasList[i])_parent.appendChild(_img)}}return elsdom}// 根据type去处理form表单getFormData(ele: any) {let copy = ele.cloneNode(true);let copiedInputs = copy.querySelectorAll('input,select,textarea');let canvasImgList = copy.querySelectorAll('.canvasImg,canvas');let selectCount = -1;// 处理所有canvasfor (let i = 0; i < canvasImgList.length; i++) {let _parent = canvasImgList[i].parentNodelet item = canvasImgList[i]// 删除克隆后的canvas节点if (item.tagName.toLowerCase() === 'canvas') {_parent.removeChild(item)} else {item.style.display = 'block'}}// 处理所有输入框for (let i = 0; i < copiedInputs.length; i++) {let item = copiedInputs[i];let typeInput = item.getAttribute('type');let copiedInput = copiedInputs[i];// 获取select标签if (!typeInput) {typeInput = item.tagName === 'SELECT' ? 'select' : item.tagName === 'TEXTAREA' ? 'textarea' : '';}// 处理input框if (item.tagName === 'INPUT') {// 除了单选框 多选框比较特别if (typeInput === 'radio' || typeInput === 'checkbox') {copiedInput.setAttribute('checked', item.checked);//} else {copiedInput.value = item.value;copiedInput.setAttribute('value', item.value);}// 处理select} else if (typeInput === 'select') {selectCount++;for (let b = 0; b < ele.querySelectorAll('select').length; b++) {let select = ele.querySelectorAll('select')[b]; // 获取原始层每一个select!select.getAttribute('newbs') && select.setAttribute('newbs', b) // 添加标识if (select.getAttribute('newbs') == selectCount) {let opSelectedIndex = ele.querySelectorAll('select')[selectCount].selectedIndex;item.options[opSelectedIndex].setAttribute('selected', true);}}// 处理textarea} else {copiedInput.innerHTML = item.value;copiedInput.setAttribute('html', item.value);}}return copy;}getPrintWindow() {let that: any = this;var f = that.Iframe();return {f: f,win: f.contentWindow || f,doc: f.doc};}Iframe() {let that: any = this;let frameId = that.settings.id;let iframe: any;try {iframe = document.createElement('iframe');document.body.appendChild(iframe);iframe.style.border = '0px';iframe.style.position = 'absolute';iframe.style.width = '0px';iframe.style.height = '0px';iframe.style.right = '0px';iframe.style.top = '0px';iframe.setAttribute('id', frameId);iframe.setAttribute('src', new Date().getTime());iframe.doc = null;iframe.doc = iframe.contentDocument ? iframe.contentDocument : (iframe.contentWindow ? iframe.contentWindow.document : iframe.document);iframe.onload = function () {var win = iframe.contentWindow || iframe;that.print(win);}} catch (e) {throw new Error(e + '. iframes may not be supported in that browser.');}if (iframe.doc == null) {throw new Error('Cannot find document.');}return iframe;}
}

main.ts中直接引入,注意目录结构

import "@/directive/vue-print-nb/print";

vue+typescript项目中无法使用vue-print-nb 打印相关推荐

  1. Vue -print - nb 打印插件 使用详解 以及连打操作

    Vue -print - nb 打印插件 #安装 npm install vue-print-nb --save #在main.js 全局引用 import Print from 'vue-print ...

  2. webpack项目中使用vue

    webpack项目中使用vue 第一步:运行 npm i vue –S 安装vue 第二步:在src->index.js入口文件中,通过 import Vue from 'vue' 来导入vue ...

  3. Vue 单文件组件||Vue 单文件组件的基本用法||webpack 中配置 vue 组件的加载器|| 在 webpack 项目中使用 vue

    Vue 单文件组件 传统组件的问题和解决方案 1. 问题 1. 全局定义的组件必须保证组件的名称不重复 2. 字符串模板缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的 \ 3. 不支持 CS ...

  4. Vue.JS项目中二级路由下刷新浏览器仍呈现当前路由的实现方案

    1.需求介绍: 以下介绍一下实现起来没什么疑问的需求:设备列表为一个主页,点击设备列表中的编辑按钮,进入设备信息主页面,默认打开设备配置页,点击设备状态.设备日志.固件升级,会切换下方内容. 本人对以 ...

  5. 多个html如何套用套一个头部,Vue.js项目中管理每个页面的头部标签的两种方法...

    在 Vue SPA 应用中,如果想要修改 HTML 的头部标签,如页面的 title ,我们只能去修改 index.html 模板文件,但是这个是全局的修改,如何为每个页面都设置不一样的 title ...

  6. vue.js项目中,关于element-ui完整引入、按需引入的介绍

    element-ui引入方式,简单说来有两种:完整引入.按需引入 首先谈一下npm安装element-ui的方法: cmd到项目目录,然后执行cmd命令:npm i element-ui -S稍等片刻 ...

  7. Vue.js项目中,当图片无法显示时则显示默认图片

    Vue.js项目中,当图片无法显示时则显示默认图片使用onerror方法 最近在学习Vue时,遇到了一个问题,就是从后台传过来的图片路径无效时,需要在页面显示默认图片 本人试了3种方法,2种方法失败了 ...

  8. html调用腾讯地图定位当前位置,vue web项目中调用腾讯地图API获取当前位置的经纬度...

    vue web项目中调用腾讯地图API获取当前位置的经纬度 vue web项目中调用腾讯地图API获取当前位置的经纬度 在main.js 中添加一下代码 import axios from 'axio ...

  9. vue+ts项目中import图片时报错Cannot find module ‘xxx‘ or its corresponding type declarations

    TS项目中import图片时报错Cannot find module 'xxx' or its corresponding type declarations 在vue+ts项目中使用import的形 ...

最新文章

  1. 大学计算机html,编程基础(C+VB+HTML)(辅)19级计算机
  2. 急速JavaScript全栈教程
  3. Redis之压缩链表ziplist
  4. 鸟哥的Linux私房菜(服务器)- 簡易 OpenWebMail 設定
  5. JUC锁框架——CyclicBarrier
  6. Coursera吴恩达《序列模型》课程笔记(2)-- NLP Word Embeddings
  7. Scikit-learn 数据预处理之最大绝对值MaxAbsScaler
  8. linux gcc出错,编译arm-linux-gcc出错
  9. java职业发展路线图_软开(Java),该如何规划职业路线?
  10. 当今互联网从业者必看书籍 -- 《自传播》
  11. java图形界面_学习Java有什么用?Java的应用领域有哪些?
  12. 海南中专学计算机的学校有哪些,​海南最好的中专学校有哪些 十大中专学校排名...
  13. nodeJS---URL相关模块用法(url和querystring)
  14. 正则划分省市区(直辖市和附详细地址包括市,区)
  15. 导出(合并)手机QQ浏览器下载的视频
  16. 《爱和自由》——孩子达到顺从的三个阶段
  17. 怎样让小孩变成机灵顾客
  18. FrontEnd笔记 -- PhotoShop
  19. 基于遗传算法优化的BP神经网络
  20. C#—得到服务器时间和国际标准时间

热门文章

  1. 数组转集合 集合转数组
  2. 豆豆趣事[2012年09月]
  3. springboot多数据源动态切换,事务下切换数据源(非分布式事务)
  4. 一次循环实现List转树形结构(不使用递归)
  5. TFS停机 文档代码暂时迁移
  6. 定制dmi信息的具体流程及相关知识
  7. 功夫熊猫经典台词:退出,不退出。做面条,不做面条。
  8. 1688API item_get - 获得1688商品详情
  9. mysql 开启远程访问_开启mysql的远程访问权限
  10. 计算机毕业设计ssm基于HTML5的流浪动物领养平台yww0b系统+程序+源码+lw+远程部署