前言

从去年年初开始,自己便下决心要写一个vue系列的博客,但时至今日,才写系列的第三篇博客,想来甚是惭愧。

但是慢归慢,每一篇都要保证质量,以及要写出自己的心路历程,防止自己工作中填的坑再让读者走一遍。

vue上手相对react来说是比较简单的,对于vue的基本指令以及语法,应该没有什么能比官网更详细,更生动的了。仔细想来,vue值得一说的,在项目中会让新手感到困惑的,是vue的组件,今天就最近工作中用到的一个pdf查看组件,和大家聊聊vue的组件。最后会讲如何将自己的代码封装成一个npm包,发布到npm官网。

去年5月份的,写了vue系列的第一篇使用vue-cli脚手架工具搭建vue-webpack项目,今天再次使用vue-cli初始化项目时,发现vue-cli已经升级到2.9.2。

多说一句,因为vue-cli的命令为vue,所以查看vue-cli的版本时,需要使用vue -V,而且是大写的V。仔细看下vue-cli 2.9的官方模板,惊喜的发现多了一个pwa模板。

前一阵子,谷歌开发者大会在上海举办,会上主推pwa,在这在简单说下PWA,大神可直接忽略。

简述PWA

PWA是Progressive Web App的缩写,字面意思理解为渐进增强的网页应用。一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能。

在一个正常的HTML中,添加一个link标签,href为manifest.json,即可将你的网页应用添加到主屏幕。

manifest.json中会包含你的图标、名称。背景色等信息。

{
"name": "你的web app名称",
"short_name": "简称",
"display": "standalone",
"start_url": "/",
"theme_color": "主体色(#ffffff)",
"background_color": "背景色(#333333)",
"icons": [
{
"src": "icon.png",
"sizes": "256x256",
"type": "image/png"
}
]
}
引入manifest.json
<link rel="manifest" href="manifest.json" />

PWA应用能实现离线访问的核心是Service Worker,Service Worker 在网页已经关闭的情况下还可以运行, 用来实现页面的缓存和离线, 后台通知等等功能。

为了让应用离线工作,需要注册一个 service worker,一段允许在后台运行的脚本,不需要 用户打开 web 页面,也不需要其他交互。在应用根目录放置serviceworker.js,然后在浏览器注册。

if('serviceWorker' in navigator) { 
  navigator.serviceWorker .register('/service-worker.js')
  .then(function() { console.log('Service Worker Registered');
}); }

  在serviceworker注册后,浏览器首次访问该应用时,会执行install方法,这个方法的callback中我们能够缓存所有需要缓存的数据。具体过程为:
首先定义需要缓存的文件类型,以及缓存存放路径;然后在网页相应所有请求之前,会将请求统一处理,可以控制一部分请求从缓存里拿数据。缓存会通过字符串名称,动态的更新。篇幅有限,这里大概简述下。具体可以移步饿了么团队知乎

vue组件vue-pdf-shower

下面言归正传,说说vue组件。

最近笔者在项目中遇到一个pdf预览的需求,经过调研,最终决定用火狐的pdf.js封装一个vue组件。

其实需求还是比较简单的,就是后台给一个URL,前端将pdf加载到网页中即可。chrome和Firefox是自带pdf查看器的,简单的做法是使用iframe嵌入,但该方案兼容性太差,而且不受我们控制,所以pass了。

总体思路如下:

1.通过pdf.js提供的api,我们传入pdf的URL,在callback中会拿到所需的pdf对象。

2.通过传入不同的页码,可以拿到指定页面的page对象。

3.通过canvas,将page对象渲染到页面中。

4.遍历所有page,循环生成多个canvas对象,插入dom。

把思路缕清楚之后,开发就比较简单了。

首先,确定dom结构。由于我们的canvas是动态插入dom的,所以只提供一个wraper即可。

dom结构如下

<template>
<div class="pdf-wraper">
<div id="cvsWraper">
<div class="loading-pdf" v-if="isloading">{{loadingTxt}}</div>
</div>
</div>
</template>

 

vue-pdf-viewer组件js

该组件需要传两个参数,一个是URL,一个是缩放值scale。

vue组件需要显式说明自身期望传入哪些属性,并且可以赋予默认值。调用组件时,传入不同的属性,可以实现父组件向子组件传值。

props: {
pdfurl: {
default: ''
},
scale: {
default: 1
}
}

  

子组件向父组件传值

子组件向父组件通信时,需要使用vue.$emit事件。

$emit事件接受两个参数,第一个为所要抛出的方法名,第二个为所抛出方法带的参数。

在这个组件中,只暴露出一个onErr事件,即当pdf加载失败时的回调函数。

PDFJS.getDocument(me.pdfurl).then(function (pafObj) {
me.isloading = true;
me.pdfDoc = pafObj;
let totalNum = me.pdfDoc.numPages; // 循环渲染所有canvas
for (let i = 1; i <= totalNum; i++) {
let id = `canvas${i}`;
let cvsNode = document.createElement('canvas');
cvsNode.setAttribute('id', id);
cvsNode.setAttribute('class', 'canvas-item');
cvsWraper.appendChild(cvsNode);
me.renderPage(i); if (totalNum === i) {
me.isloading = false;
}
}
}).catch(function (err) {
me.loadingTxt = '加载失败,请稍后重试';
me.$emit('onErr', err);
});

  

调用组件

在调用组件时,需要传入所需的属性和方法。

<template>
<div>
<pdfshower
:pdfurl="pdfurls"
:scale="scale"
@onErr="onErr"
></pdfshower>
</div>
</template>

  

非父子组件通信

兄弟组件通信也是比较常见的,比如说在一个页面中,导航是一个组件,内容区域是一个组件;当导航切换时,需要通知内容组件发生变化,并告诉他导航的id。

处理兄弟组件通信的问题,一般有两种方式:

1.兄弟组件都引入一个公共vue组件hub,通过hub抛出事件,和监听事件,以达到兄弟组件通信。

2.使用vuex。

项目中比较常见的是第一种做法,我做的vue项目中只有一次使用到了vuex;我对vuex的理解是:

vuex类似于一个全局的存储空间,你可以把他理解为将需要传递的东西绑在了window下,所以在任何地方都可以拿到,并做修改。

在项目中用到的hub.js

/**
* @file 事件总线
* @author yangtianjiao
/
import Vue from 'vue';
export default new Vue({});

  

假设是上面说的那种情况,在导航组件切换时,通过hub发射信息:

hub.$emit('changeTableData', {
dateKey: this.curDateTab
});

  

内容区域监听hub发射的方法:

hub.$on('changeTableData', item => {
this.pageNum = 1;
this.total = 0;
this.dataList = [];
this.orderFieldId = 1;
this.orderType = 1;
this.contenctDesc = '';
this.emptyText = '数据加载中...';
this.isLoading = false;
});

  

在内容组件销毁时,取消对hub事件的监听

beforeDestroy() {
hub.$off('changeTableData');
}

  

兄弟组件通信并不复杂,但要深刻理解,必须在项目中多运用、实践。这块应该是vue最难的部分了,这块掌握了,vue项目做起来就会得心应手。

发布npm包

大家平时工作中,最常用的是npm,很多包、类库都从npm安装。其实我们很容易就会发布属于自己的npm包,下面我会一步步讲讲如何将上述的vue-pdf-viewer组件发布到npm官网的。

1.执行npm init

执行npm init后,根据命令行提示,依次输入

包名称

版本

描述

入口文件

测试脚本

关键词

作者

版权信息(协议)

等等,最后OK,生成一个package.json文件。

2.确定包的目录结构

package.json是npm帮我们生成的,根目录下有入口文件index.js,和readme.md。

index.js中其实就是一句话,将真正的index.vue暴露出去

index.js

/**
* @file vue-pdf-shower
* @author v_yangtianjiao(v_yangtianjiao@baidu.com)
* @time 18/01/15
*/
module.exports = require('./lib/index.vue');

  

readme中放有对包的简述,以及包的基本用法

readme.md

# vue-pdf-shower

## 介绍
> 基于pdf.js的pdf简易查看组件。
> 该组件加载全部pdf页面,不提供翻页查看功能。 ## github
[vue-pdf-shower](https://github.com/TJ666/vue-pdf-shower) ## install
```
npm i vue-pdf-shower --save
```
## example
```
<template>
<div>
<pdfshower
:pdfurl="pdfurls"
:scale="scale"
@onErr="onErr"
></pdfshower>
</div>
</template> <script>
import pdfshower from 'vue-pdf-shower';
export default {
name: 'pdfshower',
components: {
pdfshower
},
data() {
return {
// 所查看的pdf url
pdfurls: '//cdn.mozilla.net/pdfjs/tracemonkey.pdf',
// 缩放 默认为1
scale: 1.2
};
},
methods: {
// 加载失败的callback
onErr(err) {
console.log('pdf加载失败,请重试');
console.log('错误信息:', err);
}
}
};
</script>
```

  

至于为啥有个lib文件夹,还有目录结构为啥长这样?我的回答是:

看了一遍所有的npm包都是这样,咱就按人家的来吧 - -

好了,咱们的包已经准备就绪了,就差发布!!!

3.注册npm账号&发包

打开冰箱,将大象放进冰箱,关上冰箱门。

注册很简单的,只需要一个邮箱就行,连网站都打不开的同学就好好写写jquery去吧。

4.npm login

在命令行输入npm login,

然后依次输入用户名和密码,以及注册的邮箱。

注意:输入密码时,密码是不会显示出来的,不要方!

登录后只要没有错误提示即登录成功。

5.npm publish发包

离成功只差一步。

一切准备妥当,cd 到我们的vue-pdf-shower目录,先检查下npm有没有重名的包。

可以去npm官网搜索,也可以直接npm install 包名,如果报错,那么恭喜你包名没有重复的。

执行npm publish

定睛一看,报了个错。原来是package.json 的版本号没有改。将版本号升一个级,在执行publish。

成功!

6.去npm官网检验发包情况

发现已经可以搜到,因为我是昨天发的包,一天时间内已有116次下载。嗯,还不赖。

最后附上本组件github地址,欢迎大家拍砖。
https://github.com/TJ666/vue-pdf-shower

参考文献

PWA 入门: 写个非常简单的 PWA 页面

手把手教你用npm发布一个包

【vue系列之三】从一个vue-pdf-shower,说说vue组件和npm包的更多相关文章

  1. 使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

    使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包 前端监控,埋点,数据收集,性能监控 Beacon API https://caniuse.com/beacon 优点,请 ...

  2. Vue系列——如何运行一个Vue项目

    声明 本文转自:如何运行一个Vue项目 正文 一开始很多刚入手vue.js的人,会扒GitHub上的开源项目,但是发现不知如何运行GitHub上的开源项目,很尴尬.通过查阅网上教程,成功搭建好项目环境 ...

  3. Vue系列:如何将百度地图包装成Vue的组件

    主要分解为如下步骤: (1)在html文件中引入百度地图, <script type="text/javascript" src="http://api.map.b ...

  4. vue项目中编写一个图片预览的公用组件

    今天产品提出了一个查看影像的功能需求. 在查看单据的列表中,有一列是影像字段,一开始根据单据号调用接口查看是否有图片附件,如果有则弹出一个全屏的弹出层,如果没有给出提示.而且,从列表进入详情之后,附件 ...

  5. SpringBoot系列之三_一个完整的MVC案例

    这一节让我们来做一个完整的案例. 我们将使用MyBatis作为ORM框架,并以非常简单的方式来使用MyBatis,完成一个完整的MVC案例. 此案例承接上一节,请先搭建好上一节案例. 一.数据库准备 ...

  6. 手写 Vue 系列 之 Vue1.x

    前言 前面我们用 12 篇文章详细讲解了 Vue2 的框架源码.接下来我们就开始手写 Vue 系列,写一个自己的 Vue 框架,用最简单的代码实现 Vue 的核心功能,进一步理解 Vue 核心原理. ...

  7. Vue系列:在vux的popup组件中使用百度地图遇到显示不全的问题

    问题描述: 将百度地图封装成一个独立的组件BMapComponent,具体见 Vue系列:如何将百度地图包装成Vue的组件(http://www.cnblogs.com/strinkbug/p/576 ...

  8. 从零开始写一个npm包及上传

    最近刚好自己需要写公有npm包及上传,虽然百度上资料都能找到,但是都是比较零零碎碎的,个人就来整理下,如何从零开始写一个npm包及上传. 该篇文件只记录一个大概的流程,一些细节没有记录. tips:  ...

  9. 如何发布一个包到npm && 如何使用自己发布的npm包 && 如何更新发布到npm的package && 如何更新当前项目的包?

    如何发布一个包到npm First 在https://www.npmjs.com注册一个账号. Second 编辑好项目,文件大致如下: 其中,gitignore可以如下: .DS_Store nod ...

随机推荐

  1. 五:Java之Vector类专题

    据说期末考试要考到Vector 这个类,出于复习须要在这里就要好好整理下这个类了. 一.基本概念 Vector 是可实现自己主动增长的对象数组. java.util.vector提供了向量类(vect ...

  2. 002Java概述

    1Sun(Stanford University Network )公司1995年推出的高级编程语言 2.面向Internet的编程语言 3.已经成为web应用程序的首选开发语言 4.完全面向对象简单 ...

  3. .Net 5分钟搞定网页实时监控

    一.为什么会用到网页实时监控 LZ最近在无锡买房了,虽然在上海工作,但是上海房价实在太高无法承受,所以选择还可以接受的无锡作为安身之地.买过房的小伙伴可能知道买房的流程,买房中间有一步很重要的就是需要 ...

  4. 如何处理使用js兼容所有浏览器的问题

    首先:如何处理兼容问题 1.如果两个都是属性,用逻辑||做兼容 2.如果有一个是方法,用三元做兼容 3.如果是多个属性或方法,封装函数做兼容 分享两个小知识点: 1.取消拖拽的默认行为: docume ...

  5. mongodb 3.4 集群搭建:分片+副本集

    mongodb是最常用的nodql数据库,在数据库排名中已经上升到了前六.这篇文章介绍如何搭建高可用的mongodb(分片+副本)集群. 在搭建集群之前,需要首先了解几个概念:路由,分片.副本集.配置 ...

  6. 多线程day01

    多线程作为Java中很重要的一个知识点,在此还是有必要总结一下的. 一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程 ...

  7. Xamarin使用ListView开启分组视图Cell数据展示bug处理

    问题描述 Xamarin使用IsGroupingEnabled="true"之后再Cell操作就会出现数据展示bug,数据不刷新的问题,如下图所示: 点击取消的是其他钢厂,但Vie ...

  8. 线上平滑升级nginx1.12

    .下载相关包,需要和之前用到的依赖包保持一致 wget http://nginx.org/download/nginx-1.12.2.tar.gz wget https://bitbucket.org ...

  9. Golang 网络爬虫框架gocolly/colly 四

    Golang 网络爬虫框架gocolly/colly 四 爬虫靠演技,表演得越像浏览器,抓取数据越容易,这是我多年爬虫经验的感悟.回顾下个人的爬虫经历,共分三个阶段:第一阶段,09年左右开始接触爬虫, ...

  10. vivado hls(1)

    笔记 1.vivado  hls是fpga高级综合工具,可以将C语言转换成verilog代码,适合编写算法,但是要有硬件思想. 2.软核就是只要资源足够,就可以用逻辑打一个CPU出来,与硬核不一样,硬 ...