vue加载进度组件函数式编写
一个用来显示下载文件进度的功能,如果使用普通的组件的话,一种是要在需要用的地方引入,另外一种是在最外层引入,通过vuex或eventbus传递参数调用。上面两种方法有一个弊端就是。这个组件在不使用的情况下如果不使用v-if判断都是渲染在页面的,如果使用v-if判断。又需要通过vuex eventbus等注册并监听事件。
demo
1. 声明组件
./progress.jsx
import { createApp} from 'vue';
import styled from 'vue3-styled-component'; //样式化组件,可以在js中写传统的css
import { ThemeProvider } from 'vue3-styled-component'
import { ElProgress } from 'element-plus'
//最外层
const modal = styled('div')`
position: absolute;
left:0;
top:0;
background: ${props => props.background};
height: ${props => props.prentIsBody ? '100vh' : '100%'};
width: ${props => props.prentIsBody ? '100vw' : '100%'};
z-index: 99999;
display: flex;
align-items: center;
justify-content: center;
`;
const progressInner = styled('div')`
display: flex;
width: ${(props) => (props.type=='line' ? "100%" : "unset")};
flex-direction: column;
align-items: center;
`;
const loadingText = styled('p')`
color: var(--el-color-primary);
margin: 3px 0;
font-size: 14px;
margin-top: 16px;
`;
// 进度组件
let progressComponent = {
inheritAttrs:false,
props: {
parentIsBody: {
typeof: Boolean,
require: true,
default: true
},
percentage: {
type: [Number, String, Object],
default: 0
},
bottomText: {
type: [String, Object],
default: '数据加载中!'
},
background:{
type: String,
default: 'rgba(0,0,0,.6)'
}
},
render(ctx) {
const { $props, $emit, $attrs, $slots } = ctx;
let percentage = (typeof $props.percentage == 'object') ? $props.percentage.value : $props.percentage;
let bottomText = (typeof $props.bottomText == 'object') ? $props.bottomText.value : $props.bottomText;
//pug代码
return <ThemeProvider class='theme-provider'>
<modal class='qi-progress-modal' parentIsAppendBody={$props.parentIsAppendBody} background={$props.background}>
<progressInner type={$attrs.type} class='qi-progress-inner'>
<ElProgress {...$attrs} percentage={percentage} style={{ width: (!$attrs.type || ['', 'line'].includes($attrs.type))?'95%':'unset'}}>
{$slots.default(percentage)}
</ElProgress>
<loadingText>{bottomText}</loadingText>
</progressInner>
</modal>
</ThemeProvider>
}
}
export const Qiprogress = (props = {}) => {
let warpEl = document.createElement('div');
warpEl.setAttribute('id','qi-progress-warp')
if(props.el){
if (props.el instanceof HTMLElement){
props.el.appendChild(warpEl);
}else{
document.querySelector(props.el).appendChild(warpEl);
}
}else{
document.body.appendChild(warpEl);
}
let parentIsBody = props.el?false:true;
delete props.el;
let background = props.background||null;
delete props.background;
let solts = ( props.content)||null;
delete props.content;
const app = createApp(<progressComponent>{solts}</progressComponent>,{
...props,
parentIsBody,
background
});
app.mount(warpEl);
return{
destoryed:()=>{
app.unmount(warpEl);
warpEl.remove();
}
}
}
2. 调用组件
./index.vue
import { ref } from 'vue';
import { Qiprogress } from './progress.jsx';
let progressInstance = null;
let progressOptions={
type: "circle",
percentage: ref(0),
bottomText: ref('获取数据中....'),
background:'rgba(0,0,0,.2)',
content:(data)=>{
return h('div', { class: 'tip-text' }, data+'%')
}
}
progressInstance = Qiprogress(progressOptions)
setInterval(() => {
progressOptions.percentage.value++;
if (progressOptions.percentage.value>100){
progressInstance.destoryed()
}
}, 300);
3.属性说明
| 参数 | 默认值 | 类型 | 说明 |
|---|---|---|---|
| percentage | 0 | [Number, String, Object] | 进度,如果是动态变化的需要使用ref()创建对象 |
| bottomText | 数据加载中! | [String, Object] | 底部显示的提示文字,如果是动态变化的需要使用ref()创建对象 |
| background | rgba(0,0,0,.6) | String | 背景色 |
| content | — | [String, Number,Function] | 中间显示文本,即 |
其它参数: 参考 el-progress 如:

4. 方法
| 方法名 | 说明 | 参数 |
|---|---|---|
| destoryed | 卸载组件 | — |