谁经历的苦难多,谁懂得的东西也就多。
前言
在做头像上传功能时,为了防止用户多次点击,通常会在上传时添加一个遮罩,提示用户:图片正在上传中,上传完毕后,关闭这个遮罩层,本来想找个UI框架引入进来,使用框架提供的弹层,找了很多没找到满意的,干脆自己做一个吧😂。接下来就跟大家分享下如何制作一个插件,先跟大家展示下最终实现的效果:
实现思路
- 编写加载层业务代码,实现全局加载层的相关效果
- 在插件包的index.js中进行相关封装
- 定义插件对象,实现install方法
- 使用Vue.extend构造器,将加载层业务代码作为构造器的参数创建子类
- 实例化创建的构造器,挂载到HTMLElement实例上
- 将构造器中的dom元素插入到body中
- 添加实例方法,挂载至Vue原型
- 实现显示和隐藏方法
- 插件开发完毕
实现过程
-
搭建插件开发环境
- 如图所示:在一个Vue项目的src目录下创建lib文件夹,用于存放各种插件
- 在lib文件夹下创建我们的插件文件夹(FullScreenLoading)
- 在插件文件夹下分别创建lib文件夹和index.js文件
- 插件文件夹下的lib文件夹用于存放插件需要用到的资源文件
- index.js文件用于实现这个插件的所有逻辑
-
插件业务代码(FullScreenLoading.vue)
<template>
<div id="loadingPanel" v-if="show">
<div class="container-panel">
<div class="arc"></div>
<h1><span>{{tips}}</span></h1>
</div>
</div>
</template>
<script>
export default {
name: "FullScreenLoading",
data(){
return{
tips:"加载中",
show:false
}
}
}
</script>
<style src="./css/FullScreenLoading.css">
</style>
- 插件样式代码(FullScreenLoading.css)
body {
font-family: 'Inconsolata', monospace;
overflow: hidden;
}
/*全屏遮罩层*/
#loadingPanel{
width: 100%;
height: 100%;
background: rgba(11,11,20,.6);
position: fixed;
top: 0;
left: 0;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
#loadingPanel .container-panel{
width: 200px;
height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
#loadingPanel .container-panel .arc {
width: 100px;
height: 100px;
border-radius: 50%;
border-top: 2px solid #ffea29;
border-left: 1px solid transparent;
border-right: 1px solid transparent;
animation: ring 2s infinite linear;
}
#loadingPanel .container-panel .arc::before {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 70px;
height: 70px;
border-radius: 50%;
border-top: 2px solid #8d29ff;
border-left: 1px solid transparent;
border-right: 1px solid transparent;
animation: ring 4s infinite linear reverse;
content: "";
}
#loadingPanel .container-panel .arc::after {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 0;
height: 0;
border-radius: 50%;
border-top: initial;
border-left: initial;
border-right: initial;
animation: solidCircle 1s infinite;
content: "";
background: snow;
}
#loadingPanel .container-panel h1 {
position: absolute;
height: 40px;
margin: auto;
top: 200px;
left: 0;
right: 0;
bottom: 0;
text-transform: uppercase;
text-align: center;
letter-spacing: 0.1em;
font-size: 14px;
font-weight: bold;
color: white;
}
/*动画定义*/
@keyframes ring {
100% {
transform: rotate(360deg);
}
}
@keyframes solidCircle {
0% {
width: 0;
height: 0;
}
75% {
width: 40px;
height: 40px;
}
100% {
width: 0;
height: 0;
}
}
- 插件逻辑文件(index.js)
// 引入对应的组件
import loading from "./lib/FullScreenLoading";
// 定义对象:开发插件对象
const LoadPlugin = {
// 插件包含install方法
install(Vue,options){
// 使用Vue.extend构造器,创建一个子类,参数为引入的FullScreenLoading组件
const loadingSubclass = Vue.extend(loading);
// 实例化loadingSubclass,挂载到HTMLElement实例上
const Profile = new loadingSubclass({
el: document.createElement('div')
});
// 插入到body中,FullScreenLoading.vue中的template模板内容将会替换挂载的元素,Profile.el中到内容最终为模版到内容
document.body.appendChild(Profile.$el);
// 判断是否有传参数:替换组件内的默认显示数据
if(options){
if(options.tips){
Profile.tips = options.tips;
}
}
// 添加实例方法,挂载至Vue原型
Vue.prototype.$fullScreenLoading = {
// 定义显示隐藏的方法
show(tips) {
Profile.show = true;
if (tips) {
// 替换组件的默认数据
Profile.tips = tips;
}
},
hide() {
Profile.show = false;
}
};
}
};
// 导出对象
export default LoadPlugin;
至此,插件开发完毕。本文开头实现的效果,项目地址:chat-system
插件发布
- 在终端进入到FullScreenLoading文件夹内
- 创建README.md编写插件描述以及使用方法
- 终端执行npm init命令,生成package.json文件
npm init
# 应用包名,要先去https://www.npmjs.com/官网查一下是否与你的包重复
package name: (@likaia/vue-fullscreenloading)
# 版本号
version: (1.0.0)
# 包描述
description: 全屏加载层插件,提升用户体验,防止用户误操作。
# 入口文件
entry point: (index.js)
# 测试命令,直接回车即可
test command:
# 项目git仓库地址
git repository: https://github.com/likaia/chat-system.git
# 关键词:用户在npm官网搜索包时所用的关键词
keywords: vue-loading FullScreenLoading
# 作者
author: likaia
# 开源协议,直接回车即可
license: (ISC)
- 发布到npm仓库
# 登录,没有账号的需要先去官网注册:https://www.npmjs.com/
npm login
# 发布至npm
npm publish --access public
登录成功
发布成功
- 在npm官网搜索刚才发布的包
使用插件
-
终端执行: yarn add @likaia/vue-fullscreenloading
-
在main.js中进行引用
import FullScreenLoading from '@likaia/vue-fullscreenloading'
Vue.use(FullScreenLoading);
- 在业务中使用
uploadAvatar:function (e) {
console.log("上传点击了");
// 显示全局加载层
this.$fullScreenLoading.show("上传中");
let file = e.target.files[0];
// 构造form对象
let formData = new FormData();
// 后台取值字段 | blob文件数据 | 文件名称
formData.append("file",file,file.name);
// 调用上传api
this.$api.fileManageAPI.baseFileUpload(formData).then((res)=>{
console.log(res);
const fileName = `${base.lkBaseURL}/uploads/${res.fileName}`;
// 更改默认头像状态
this.isDefaultAvatar = false;
// 头像赋值
this.avatarSrc = fileName;
// 隐藏全局加载层
this.$fullScreenLoading.hide();
});
console.log(e);
}
写在最后
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊
- 本文首发于掘金,如需转载请评论区留言💌
评论区