这是我参与更文挑战的第3天,活动详情查看:更文挑战
昨天发布了自己第一个认认真真写的 Vue 组件,有兴趣的可以看下:来动手打造一款自己的大图预览组件~,昨天已经把组件的基本功能(包括放大,缩写,旋转,还原)完成了,今天又加上了下载,虽然下载好像没什么用,右键另存为就可以了,但下载写着写着发现还是不少知识点的,比如要对不同的src地址(httpURL,base64,本地地址)来进行下载文件,一会贴上代码,大家可以看一下~ 然后就是对项目进行一点配置,上传到npm,供其他项目或者有需求的朋友使用(不管你们用不用,反正我自己感觉我的组件挺好用,哈哈哈~)。
1. 下载功能实现
// utils/index.js
// blob下载
export async function downFile(url, fileName = "download") {
try {
let blob = null;
// 本地图片 网络图片 base64图片处理
if (url.startsWith("http")) {
blob = await getBlob(url);
} else if (url.startsWith("data:image")) {
let mime = getBase64Type(url);
blob = mime ? dataURLtoBlob(url, mime) : dataURLtoBlob(url);
} else if (url.startsWith("/")) {
blob = await getBlob(window.origin + url);
} else {
return;
}
let a = document.createElement("a");
a.download = fileName;
a.href = window.URL.createObjectURL(blob);
a.click();
} catch (error) {
console.log(error);
}
}
// 将base64转为blob
export function dataURLtoBlob(base64, mimeType = "image/png") {
let bytes = window.atob(base64.split(",")[1]);
let ab = new ArrayBuffer(bytes.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], { type: mimeType });
}
// 将网络url转为blob
export function getBlob(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = () => {
if (xhr.status == 200) {
resolve(xhr.response);
} else {
reject();
}
};
xhr.send();
});
}
// 获取base64文件类型
export function getBase64Type(base64) {
let index0 = base64.indexOf(":");
let index1 = base64.indexOf(";");
let mime = "";
if (index0 !== -1 && index1 !== -1) {
mime = base64.slice(index0 + 1, index1);
}
return mime;
}
复制代码
2. 组件发布
组件注册工具函数
// 引入组件
import imgLargeMode from "@/components/img-large-mode";
// install方法,以供Vue.use()注册使用
const install = (Vue, option) => {
// 创建构造器,生成一个Vue实例
const componentInstance = Vue.extend(imgLargeMode);
// 定义实例化对象
let currentComponent = null;
// 对象实例化,将组件挂载到body下
const initInstance = () => {
currentComponent = new componentInstance();
let componentEL = currentComponent.$mount().$el;
document.body.appendChild(componentEL);
};
// 定义用户使用的方法,挂在到Vue
Vue.prototype.$_openLargeMode = {
show(opt) {
initInstance();
return currentComponent.show(opt);
}
};
};
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export default {
install,
imgLargeMode
};
复制代码
package.json
{
"name": "img-large-mode",
"version": "0.1.0",
"main": "./dist/img-large-mode.umd.min.js",
"author": "Tmier",
"description": "基于Vue的大图模式组件",
"keywords": [
"img-large-mode",
"img-large",
"large-mode"
],
"repository": {
"type": "git",
"url": "https://github.com/itmier/img-large-mode"
},
"license": "MIT",
"files": [
"dist"
],
"private": false,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"package": "vue-cli-service build --target lib --name img-large-mode --dest dist ./src/components/index.js",
"lint": "vue-cli-service lint"
},
"dependencies": {
...
},
"devDependencies": {
...
}
}
复制代码
组件发布的package.json
具体说明:
name: 组件名称,包名,必须有且不能重复
version: 版本号,发布时必填
main: 入口函数,启动项目的文件
如果包由用户安装,则用户执行
require('foo-lib')
时,这时require
将返回main
字段所列出的文件的module.exports
属性author: 作者
description: 描述
keywords: 关键词
license: 许可证
repository: 记录代码所在的资源库
private: 默认true,发布包时要设置为false,否则npm会拒绝发布它
files: 是一个文件数组,描述了将软件包作为依赖项安装时要包括的条目。如果在数组里面声明了一个文件夹,那么也会包含文件夹中的文件。某些特殊文件和目录也会被包括或者排除在外,无论它们是否存在于文件数组中。
以下文件无论是否设置,总是包含: * `package.json` * `README` * `CHANGES`/`CHANGELOG`/`HISTORY` * `LICENSE`/`LICENCE` * `NOTICE` * The file in the “main” field 以下文件总是被忽略: * `.git` * `CVS` * `.svn` * `.hg` * `.lock-wscript` * `.wafpickle-N` * `.*.swp` * `.DS_Store` * `._*` * `npm-debug.log` * `.npmrc` * `node_modules` * `config.gypi` * `*.orig` * `package-lock.json`(use shrinkwrap instead) 复制代码
在scripts
中新添加一条命令,我觉得得记录一下:
"package": "vue-cli-service build --target lib --name img-large-mode --dest dist ./src/components/index.js"
复制代码
用法:vue-cli-service build [options] [entry|pattern]
选项:
--mode 指定环境模式 (默认值:production)
--dest 指定输出目录 (默认值:dist)
--modern 面向现代浏览器带自动回退地构建应用
--target app | lib | wc | wc-async (默认值:app)
--name 库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名)
--no-clean 在构建项目之前不清除目标目录
--report 生成 report.html 以帮助分析包内容
--report-json 生成 report.json 以帮助分析包内容
--watch 监听文件变化
复制代码
索引上面我加的那条命令可以解释为: 构建命令 构建目标 库 名称 img-large-mode 输出目录 dist 函数入口
PS: 这个入口可以是一个
.js
或一个.vue
文件。如果没有指定入口,则会使用src/App.vue
。
配置完成,接下来就是npm发布~
npm发布包
npm login //输入用户名密码登录npm,没有的话去注册
npm run package(自己定义的scripts打包命令)
npm publish
复制代码
ok,发布成功,大功告成~
还差一点,写文章的时候在家里的电脑上安装了一下自己发布的包,然后发现会带着vue
,vuex
,vue-router
,是不是我有地方没有配置好?我安装了一下element-ui
,发现它没有安装vue相关库,有没有大佬指点一下~
3. 展望
完善组件功能,目前能想到的就下面几个,有看到的可以补充一下:
- 支持数组List,图片可以实现上一张下一张查看
- 像
ant design
一样的modal
动画效果,为图片遮罩添加动画