精华内容
下载资源
问答
  • 本文介绍一款非常好用打印插件--...你可以使用如下命令通过 npm 安装 vue-print-nb: cnpm install vue-print-nb 安装完成后: main.js引入 import Print from 'vue-print-nb' Vue.use(Print); //注册 Vue代码
    本文介绍一款非常好用打印插件--vue-print-nb
    • 之前我看过我们教务系统,里面使用的是jq+layui打印,我也玩过,但封装的一直不理想,就想换一个。在网上就找到了这个。

    npm安装vue-print-nb

    你可以使用如下命令通过 npm 安装 vue-print-nb:

    cnpm install vue-print-nb
    

    安装完成后:

    • 在main.js中引入
    import Print from 'vue-print-nb'
    
    Vue.use(Print);  //注册
    

    使用vue-print-vue

    Vue代码中的使用:

    <template>
    	<div>
    	  <div id="printTest" >	
          <p>锄禾日当午</p>
          <p>汗滴禾下土 </p>	
          <p>谁知盘中餐</p>	
          <p>粒粒皆辛苦</p>	
       </div>	
    	 <button v-print="'#printTest'">打印</button>
    	</div>
    </template>
    
    <script>
    
    </script>
    
    <style>
    
    </style>
    

    在这里插入图片描述
    在这里插入图片描述
    如果打印内容不全,在打印操作时点击更多操作,然后设置缩放:
    在这里插入图片描述

    展开全文
  • 前言:在项目需求中有遇到将当前的表格信息打印出来的功能,将网上的方法整理成一个详细的操作步骤,希望多点点赞噢~ 1.引入插件 ...2.在vue文件中使用 <template> <div id="printMe" ref="print

    前言:在项目需求中有遇到将当前的表格信息打印出来的功能,将网上的方法整理成一个详细的操作步骤,希望多点点赞噢~

    1.引入插件

    这里采用的插件是 vue-print-nb
    安装 
    npm install vue-print-nb --save
    
    在vue文件中的main.js文件中注册 
    import Print from 'vue-print-nb'
    Vue.use(Print);
    

    2.在vue文件中使用

    <template>
    	<div id="printMe" ref="print" v-show="isPrint">
    		<p>这里面就是需要打印的内容</p>
    	</div>
    	<button @click="print">打印</button>
    </template>
    <script>
    	export default{
    		data(){
    			return{
    				isPrint:false, //控制当前打印页面是否显示
    			}
    		},
    		methods:{
    			print(){
    				this.isPrint = true,
    				setTimeout(()=>{
    		        	this.isPrint = false
    		      },100)
    			}
    		}
    	}
    </script>
    
    展开全文
  • 首先:main.js import Print from '@/utils/print' // ...Vue.use(Print); 页面: <div style="display: none"> //dispaly 用于显示或隐藏你需要打印的部分。 <div ref="print" > //命名ref...

    首先:在main.js中

    import Print from '@/utils/print' // 引入js文件
    Vue.use(Print);
    

    在页面中:

      <div style="display: none">   //dispaly 用于显示或隐藏你需要打印的部分。
                        <div  ref="print" >   //命名ref为print,该部分为要打印的部分,(不使用id命名的原因,为了防止webpack打包时,打印内容为空。) 
                            ....                    //这里为要打印的表单内容,样式最好为内联样式。
                        </div>
     </div>
    

    打印按钮:

        <el-button  type="primary" size="small" icon="iconfont icon-printer" @click="printReport()">打印</el-button>
    

    function:

         // 打印
                printReport() {
                    if(this.Selection.length>0){
                        this.$print(this.$refs.print)    //调用打印,$refs.print(print为ref命名)
                    }else {
                        this.$message(
                            {
                                message: '请先选中已表格一行或者多行数据!',
                                type: 'warning'
                            }
                        )
                    }
                },
    

    最后,附上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.dom = dom;
        }
    
        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 in inputs) {
                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)
                }
            }
    
            for (var k2 in textareas) {
                if (textareas[k2].type == 'textarea') {
                    textareas[k2].innerHTML = textareas[k2].value
                }
            }
    
            for (var k3 in selects) {
                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;";
    
            w = f.contentWindow || f.contentDocument;
            doc = f.contentDocument || f.contentWindow.document;
            doc.open();
            doc.write(content);
            doc.close();
            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);
            }
        }
    };
    const MyPlugin = {}
    MyPlugin.install = function (Vue, options) {
        // 4. 添加实例方法
        Vue.prototype.$print = Print
    }
    export default MyPlugin
    
    
    展开全文
  • 在Vue项目中使用snapshot测试 snapshot介绍 snapshot测试又称快照测试,可以直观地反映出组件UI是否发生了未预见到的变化。snapshot如字面上所示,直观描述出组件的样子。通过对比前后的快照,可以很快找出UI的变化...

    在Vue项目中使用snapshot测试

    snapshot介绍

    snapshot测试又称快照测试,可以直观地反映出组件UI是否发生了未预见到的变化。snapshot如字面上所示,直观描述出组件的样子。通过对比前后的快照,可以很快找出UI的变化之处。

    第一次运行快照测试时会生成一个快照文件。之后每次执行测试的时候,会生成一个快照,然后对比最初生成的快照文件,如果没有发生改变,则通过测试。否则测试不通过,同时会输出结果,对比不匹配的地方。

    jest中的快照文件以为snap拓展名结尾,格式如下(ps: 在没有了解之前,我还以为是快照文件是截图)。一个快照文件中可以包含多个快照,快照的格式其实是HTML字符串,对于UI组件,其HTML会反映出其内部的state。每次测试只需要对比字符串是否符合初始快照即可。

    exports[`button 1`] = `"<div><span class=\\"count\\">1</span> <button>Increment</button> <button class=\\"desc\\">Descrement</button> <button class=\\"custom\\">not emitted</button></div>"`;

    snapshot测试不通过的原因有两个。一个原因是组件发生了未曾预见的变化,此时应检查代码。另一个原因是组件更新而快照文件并没有更新,此时要运行jest -u更新快照。

    › 1 snapshot failed from 1 test suite. Inspect your code changes or re-run jest with -u to update them.

    结合Vue进行snapshot测试

    生成快照时需要渲染并挂载组件,在Vue中可以使用官方的单元测试实用工具Vue Test Utils

    Vue Test Utils 提供了mountshallowMount这两个方法,用于创建一个包含被挂载和渲染的 Vue 组件的 Wrapper。component是一个vue组件,options是实例化Vue时的配置,包括挂载选项和其他选项(非挂载选项,会将它们通过extend覆写到其组件选项),结果返回一个包括了一个挂载组件或 vnode,以及测试该组件或 vnode 的方法的Wrapper实例。

    mount(component:{Component}, options:{Object})

    shallowMountmount不同的是被存根的子组件,详细请戳文档

    Wrapper上的丰富的属性和方法,足以应付本文中的测试需求。html()方法返回Wrapper DOM 节点的 HTML 字符串。find()findAll()可以查找Wrapper里的DOM节点或Vue组件,可用于查找监听事件的元素。trigger可以在DOM节点/组件上触发一个事件。

    结合上述的方法,我们可以完成一个模拟事件触发的快照测试。

    细心的读者可能会发现,我们平时在使用Vue时,数据更新后视图并不会立即更新,需要在nextTick回调中处理更新完成后的任务。但在 Vue Test Utils 中,为简化用法,更新是同步的,所以无需在测试中使用 Vue.nextTick 来等待 DOM 更新。

    demo演示

    Vue Test Utils官方文档中提供了一个集成VTU和Jest的demo,不过这个demo比较旧,官方推荐用CLI3创建项目。

    执行vue create vue-snapshot-demo创建demo项目,创建时要选择单元测试,提供的库有Mocha + ChaiJest,在这里选择Jest.安装完成之后运行npm run serve即可运行项目。

    本文中将用一个简单的Todo应用项目来演示。这个Todo应用有简单的添加、删除和修改Todo项状态的功能;Todo项的状态有已完成和未完成,已完成时不可删除,未完成时可删除;已完成的Todo项会用一条线横贯文本,未完成项会在鼠标悬浮时展示删除按钮。

    组件简单地划分为Todo和TodoItem。TodoItem在Todo项未完成且触发mouseover事件时会展示删除按钮,触发mouseleave时则隐藏按钮(这样可以在快照测试中模拟事件)。TodoItem中有一个checkbox,用于切换Todo项的状态。Todo项完成时会有一个todo-finished类,用于实现删除线效果。

    为方便这里只介绍TodoItem组件的代码和测试。

    <template>
      <li
        :class="['todo-item', item.finished?'todo-finished':'']"
        @mouseover="handleItemMouseIn"
        @mouseleave="handleItemMouseLeave"
      >
        <input type="checkbox" v-model="item.finished">
        <span class="content">{{item.content}}</span>
        <button class="del-btn" v-show="!item.finished&&hover" @click="emitDelete">delete</button>
      </li>
    </template>
    
    <script>
    export default {
      name: "TodoItem",
      props: {
        item: Object
      },
      data() {
        return {
          hover: false
        };
      },
      methods: {
        handleItemMouseIn() {
          this.hover = true;
        },
        handleItemMouseLeave() {
          this.hover = false;
        },
        emitDelete() {
          this.$emit("delete");
        }
      }
    };
    </script>
    <style lang="scss">
    .todo-item {
      list-style: none;
      padding: 4px 16px;
      height: 22px;
      line-height: 22px;
      .content {
        margin-left: 16px;
      }
      .del-btn {
        margin-left: 16px;
      }
      &.todo-finished {
        text-decoration: line-through;
      }
    }
    </style>

    进行快照测试时,除了测试数据渲染是否正确外还可以模拟事件。这里只贴快照测试用例的代码,完整的代码戳我

    describe('TodoItem snapshot test', () => {
        it('first render', () => {
            const wrapper = shallowMount(TodoItem, {
                propsData: {
                    item: {
                        finished: true,
                        content: 'test TodoItem'
                    }
                }
            })
            expect(wrapper.html()).toMatchSnapshot()
        })
    
        it('toggle checked', () => {
            const renderer = createRenderer();
            const wrapper = shallowMount(TodoItem, {
                propsData: {
                    item: {
                        finished: true,
                        content: 'test TodoItem'
                    }
                }
            })
            const checkbox = wrapper.find('input');
            checkbox.trigger('click');
            renderer.renderToString(wrapper.vm, (err, str) => {
                expect(str).toMatchSnapshot()
            })
        })
        
        it('mouseover', () => {
            const renderer = createRenderer();
            const wrapper = shallowMount(TodoItem, {
                propsData: {
                    item: {
                        finished: false,
                        content: 'test TodoItem'
                    }
                }
            })
            wrapper.trigger('mouseover');
            renderer.renderToString(wrapper.vm, (err, str) => {
                expect(str).toMatchSnapshot()
            })
        })
    })

    这里有三个测试。第二个测试模拟checkbox点击,将Todo项从已完成切换到未完成,期待类todo-finished会被移除。第三个测试在未完成Todo项上模拟鼠标悬浮,触发mouseover事件,期待删除按钮会展示。

    这里使用toMatchSnapshot()来进行匹配快照。这里生成快照文件所需的HTML字符串有wrapper.html()Renderer.renderToString这两种方式,区别在于前者是同步获取,后者是异步获取。

    测试模拟事件时,最好以异步方式获取HTML字符串。同步方式获取的字符串并不一定是UI更新后的视图。

    尽管VTU文档中说所有的更新都是同步,但实际上在第二个快照测试中,如果使用expect(wrapper.html()).toMatchSnapshot(),生成的快照文件中Todo项仍有类todo-finished,期待的结果应该是没有类todo-finished,结果并非更新后的视图。而在第三个快照测试中,使用expect(wrapper.html()).toMatchSnapshot()生成的快照,按钮如期望展示,是UI更新后的视图。所以才不建议在DOM更新的情况下使用wrapper.html()获取HTML字符串。

    下面是两种对比的结果,1是使用wrapper.html()生成的快照,2是使用Renderer.renderToString生成的。

    exports[`TodoItem snapshot test mouseover 1`] = `<li class="todo-item"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn" style="">delete</button></li>`;
    
    exports[`TodoItem snapshot test mouseover 2`] = `<li class="todo-item"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn">delete</button></li>`;
    
    exports[`TodoItem snapshot test toggle checked 1`] = `<li class="todo-item todo-finished"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn" style="display: none;">delete</button></li>`;
    
    exports[`TodoItem snapshot test toggle checked 2`] = `<li class="todo-item"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn" style="display:none;">delete</button></li>`;

    这里使用vue-server-renderer提供的createRenderer来生成一个Renderer实例,实例方法renderToString来获取HTML字符串。这种是典型的回调风格,断言语句在回调中执行即可。

        // ...
        wrapper.trigger('mouseover');
        renderer.renderToString(wrapper.vm, (err, str) => {
            expect(str).toMatchSnapshot()
        })

    如果不想使用这个库,也可以使用VTU中提供的异步案例。由于wrapper.html()是同步获取,所以获取操作及断言语句需要在Vue.nextTick()返回的Promise中执行。

        // ...
        wrapper.trigger('mouseover');
        Vue.nextTick().then(()=>{
            expect(wrapper.html()).toMatchSnapshot()
        })

    观察测试结果

    执行npm run test:unityarn test:unit运行测试。

    初次执行,终端输出会有Snapshots: 3 written, 3 total这一行,表示新增三个快照测试,并生成初始快照文件。

     › 3 snapshots written.
    Snapshot Summary
     › 3 snapshots written from 1 test suite.
    
    Test Suites: 1 passed, 1 total
    Tests:       7 passed, 7 total
    Snapshots:   3 written, 3 total
    Time:        2.012s
    Ran all test suites.
    Done in 3.13s.

    快照文件如下示:

    // Jest Snapshot v1, https://goo.gl/fbAQLP
    
    exports[`TodoItem snapshot test first render 1`] = `<li class="todo-item todo-finished"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn" style="display: none;">delete</button></li>`;
    
    exports[`TodoItem snapshot test mouseover 1`] = `<li class="todo-item"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn">delete</button></li>`;
    
    exports[`TodoItem snapshot test toggle checked 1`] = `<li class="todo-item"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn" style="display:none;">delete</button></li>`;

    第二次执行测试后,输出中有Snapshots: 3 passed, 3 total,表示有三个快照测试成功通过,总共有三个快照测试。

    Test Suites: 1 passed, 1 total
    Tests:       7 passed, 7 total
    Snapshots:   3 passed, 3 total
    Time:        2s
    Ran all test suites.
    Done in 3.11s.

    修改第一个快照中传入的content,重新运行测试时,终端会输出不匹配的地方,输出数据的格式与Git类似,会标明哪一行是新增的,哪一行是被删除的,并提示不匹配代码所在行。

        - Snapshot
        + Received
    
        - <li class="todo-item todo-finished"><input type="checkbox"> <span class="content">test TodoItem</span> <button class="del-btn" style="display: none;">delete</button></li>
        + <li class="todo-item todo-finished"><input type="checkbox"> <span class="content">test TodoItem content change</span> <button class="del-btn" style="display: none;">delete</button></li>
    
          88 |             }
          89 |         })
        > 90 |         expect(wrapper.html()).toMatchSnapshot()
             |                                ^
          91 |     })
          92 |
          93 |     it('toggle checked', () => {
    
          at Object.toMatchSnapshot (tests/unit/TodoItem.spec.js:90:32)
    

    同时会提醒你检查代码是否错误或重新运行测试并提供参数-u以更新快照文件。

    Snapshot Summary
     › 1 snapshot failed from 1 test suite. Inspect your code changes or re-run jest with `-u` to update them.

    执行npm run test:unit -- -uyarn test:unit -u更新快照,输出如下示,可以发现有一个快照测试的输出更新了。下次快照测试对照的文件是这个更新后的文件。

    Test Suites: 1 passed, 1 total
    Tests:       7 passed, 7 total
    Snapshots:   1 updated, 2 passed, 3 total
    Time:        2.104s, estimated 3s
    Ran all test suites.
    Done in 2.93s.

    其他

    除了使用toMatchSnapshot()外,还可以使用toMatchInlineSnapshot()。二者不同之处在于toMatchSnapshot()从快照文件中查找快照,而toMatchInlineSnapshot()则将传入的参数当成快照文件进行匹配。

    配置Jest

    Jest配置可以保存在jest.config.js文件里,可以保存在package.json里,用键名jest表示,同时也允许行内配置。

    介绍几个常用的配置。

    rootDir

    查找Jest配置的目录,默认是pwd

    testMatch

    jest查找测试文件的匹配规则,默认是[ "**/__tests__/**/*.js?(x)", "**/?(*.)+(spec|test).js?(x)" ]。默认查找在__test__文件夹中的js/jsx文件和以.test/.spec结尾的js/jsx文件,同时包括test.jsspec.js

    snapshotSerializers

    生成的快照文件中HTML文本没有换行,是否能进行换行美化呢?答案是肯定的。

    可以在配置中添加snapshotSerializers,接受一个数组,可以对匹配的快照文件做处理。jest-serializer-vue这个库做的就是这样任务。

    如果你想要实现这个自己的序列化任务,需要实现的方法有testprinttest用于筛选处理的快照,print返回处理后的结果。

    后记

    在未了解测试之前,我一直以为测试是枯燥无聊的。了解过快照测试后,我发现测试其实蛮有趣且实用,同时由衷地感叹快照测试的巧妙之处。如果这个简单的案例能让你了解快照测试的作用及使用方法,就是我最大的收获。

    如果有问题或错误之处,欢迎指出交流。

    参考链接

    展开全文
  • vue项目中使用jsx语法

    千次阅读 2018-05-19 15:10:01
    vue项目中使用jsx语法 1、官方文档传送门 2、github上插件传送门 一、环境搭建步骤 1、使用vue-cli构建一个项目 2、安装依赖包 yarn add babel-plugin-syntax-jsx babel-plugin-transform-vue-jsx babel-...
  • 本文主要介绍了vue项目中使用print.js打印,解决多页,分页,打印预览样式修改等问题。 引入安装vue-print.js cnpm i vue-printjs --save-dev 解决打印多页只出现一页问题 由于打印插件存在问题,如果打印文件...
  • 前言:最近之前的vue项目中,文章详情页面的打印功能出了问题,之前用的是vue-print-nb,现在有的客户反馈出现打印页面不完整的问题(客户用的国产的浏览器),所以想换一种写法处理这个问题,发现js原生就有打印的...
  • vue项目改造成对typescript支持的项目后,vue-print-nb打印指令无法使用 尝试有没有对应的typescript包,发现没有 解决办法 node_modules目录下找到vue-print-nb,复制出src/packages目录下的print.js和printarea.js...
  • Vue 项目中使用Lodop进行打印

    千次阅读 2019-06-18 21:56:40
    配置文件与地址 ...建议在项目中建一个自己的工具方法文件夹,使用方便 相信大家截图已经看到了,有个lodop.js的文件,没错!核心的一大坨都里面,这里直接上代码 var CreatedOKLodop7766 = null ...
  • 如何在vue项目中使用lodop打印插件

    千次阅读 2018-12-18 23:24:47
     先写了个webdemo  ... To change this template use File | Settings | ... 费用项目  ; vertical-align:top; width:81.6500pt"> 付款金额  ; vertical-align:top; width:77.7000pt"> 备注...
  • Vue项目中使用Tinymce

    千次阅读 2019-05-10 23:54:44
    前言最近因为公司项目的后台管理端需要实现编辑器功能, 一方面满足编辑各类文章内容需求,另一方面要自己编辑一些课程相关的介绍,于是就花了一些时间对比体验现有的一些开源的编辑...
  • 第一种方法:使用window自带的打印功能 html <div id="printBox" ref="printContent> 打印内容 </div> <button @click="print">打印</button> js print(){ // 获取要打印的dom内容 let ...
  • 标题所说的像使用vue-router那样使用axios,就是在Vue.prototype加入$axios。Object.defineProperty(Vue.prototype, '$axios', { get () { return axios } }) 下面我会介绍一下我解决这个问题的路程,感...
  • vue中使用vue-print-nb实现打印功能

    千次阅读 2020-08-06 15:20:08
    vue中使用vue-print-nb实现打印功能 安装: npm install vue-print-nb --save main.js中引入: import Print from 'vue-print-nb' Vue.use(Print); 页面中使用: <div id="printTest">打印的内容</div&...
  • 在VUE项目中实现打印

    2021-04-28 21:39:01
    mian.js引入 import Print from 'vue-print-nb' Vue.use(Print); <el-dialog title="打印页面" :visible.sync="dialogVisible" width="40%" :loading="loading" size='small' @open="dialogOpen"> <...
  • vue项目中使用lodop实现打印

    千次阅读 2019-02-21 18:08:46
    先说一下 Lodop 是什么东西吧 官网有详细介绍我就不多说啦 官网: ... ...(标音:劳道谱,俗称:露肚皮)是专业WEB控件,用它既可裁剪输出页面内容,又可用程序代码直接实现 ...3.页面中使用 先要引入你这个lodop.js哦 ...
  • 一个Vue.js项目 构建设置 # install dependencies npm install # serve with hot reload at localhost:8080 npm run dev # build for production with minification npm run build # build for production and view...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,572
精华内容 2,228
关键字:

print在vue项目中的使用

vue 订阅