Vue implements interface progress bar

9d40cf3ad5fa63ca0d0ddda00796c10d.jpeg

When the front-end requests information from the back-end, it often needs to wait for a certain period of time to get the returned result. In order to improve user experience, you can increase the interactivity and visual effect of the page by implementing an interface progress bar function.

046fa8db78d0234ce28dfa2c010bf16b.jpeg

Fast interface response - effect

9f5b5b6697f24f48feb4c760ab52d917.jpeg

Slow interface response - effect

Implementation ideas

First define a progress bar component to render the page display effect. The component includes the progress bar background, progress length, and progress number, and also sets data binding related properties, such as the current percentage of the progress bar, animation execution status, and completion status, etc. . In the process of requesting data, you need to add a listening function to monitor the process changes of the data request, and update the corresponding properties and interface elements of the component.

Code

The following is a chestnut that uses Vue to implement an interface progress bar:

<template>
    <div class="progress-bar">
        <div class="bg"></div>
        <div class="bar" :style="{ width: progress + '%' }"></div>
        <div class="label">{
    
    { progress }}%</div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            progress: 0,
            isPlaying: false,
            isCompleted: false
        }
    },
    mounted() {
        this.start();
    },
    methods: {
        start() {
            this.isPlaying = true;
            this.animateProgress(90)
                .then(() => {
                    if (!this.isCompleted) {
                        this.animateProgress(100);
                    }
                })
                .catch((error) => {
                    console.error('Progress error', error);
                });
        },
        animateProgress(target) {
            return new Promise((resolve, reject) => {
                let start = this.progress;
                const end = target;
                const duration = (target - start) * 150;

                const doAnimation = () => {
                    const elapsed = Date.now() - startTime;
                    const progress = Math.min(elapsed / duration, 1);

                    this.progress = start + ((end - start) * progress);

                    if (progress === 1) {
                        resolve();
                    } else if (this.isCompleted) {
                        resolve();
                    } else {
                        requestAnimationFrame(doAnimation);
                    }
                };

                const startTime = Date.now();
                requestAnimationFrame(doAnimation);
            });
        },
        finish() {
            this.isCompleted = true;
            this.progress = 100;
        }
    }
};
</script>

<style scoped>
.progress-bar {
    position: relative;
    height: 8px;
    margin: 10px 0;
}
.bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #ccc;
    border-radius: 5px;
}
.bar {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    border-radius: 5px;
    background-color: #409eff;
    transition: width 0.5s;
}
.label {
    position: absolute;
    top: -20px;
    left: calc(100% + 5px);
    color: #333;
    font-size: 12px;
}
</style>
复制代码

First, three data attributes are defined to control the playback and completion status of the animation, which are the current scale of the progress bar  progress, animation playback status  isPlaying, and animation completion status  isCompleted. In the process of component initialization,  start the method is called to start the progress bar animation effect. Inside the method, use a Promise to move from 0% to 90% to the corresponding position and stop when it reaches that position.

Determine whether it is currently completed, if not, call again  animateProgress(100) , and check whether there is data returned during progress loading. If it exists, stop the first half of the animation and fill the progress bar to 100% in 1 second.

Here's how to add a listener function in the process of requesting data:

import axios from 'axios';
import ProgressBar from './ProgressBar.vue';

const progressBar = new Vue(ProgressBar).$mount();
document.body.appendChild(progressBar.$el);
复制代码

In this code snippet, the Axios interceptor is used to monitor the progress of the request. Before the request starts, add a progress bar component to the page, then mount the component to the page and append its element to the  <body> end of the HTML markup.

Next,  onDownloadProgress monitor the change of the download progress through the monitoring function. Remove the progress bar component if loading is complete. At the same time, it is also possible to set different progress bars for ajax requests using different APIs to achieve better user experience.

axios.interceptors.request.use((config) => {    
    const progressBar = new Vue(ProgressBar).$mount();
    document.body.appendChild(progressBar.$el);

    config.onDownloadProgress = (event) => {
        if (event.lengthComputable) {
            progressBar.progress = parseInt((event.loaded / event.total) * 100, 10);  
            if (progressBar.progress === 100) {
                progressBar.finish();
                setTimeout(() => {
                    document.body.removeChild(progressBar.$el);
                }, 500);
            }
        }
    };

    return config;
}, (error) => {
    return Promise.reject(error);
});
复制代码

parameter injection

In order to flexibly adjust the effect of the interface progress bar, parameter injection can be used to control the setting of animation speed and completion time. In  animateProgress the function, use parameters to set the percentage range and animation playback speed, so as to get different effects of progress bar and playback time.

animateProgress(target, duration) {
    return new Promise((resolve, reject) => {
        let start = this.progress;
        const end = target;

        const doAnimation = () => {
            const elapsed = Date.now() - startTime;
            const progress = Math.min(elapsed / duration, 1);

            this.progress = start + ((end - start) * progress);

            if (progress === 1) {
                resolve();
            } else if (this.isCompleted) {
                resolve();
            } else {
                requestAnimationFrame(doAnimation);
            }
        };

        const startTime = Date.now();
        requestAnimationFrame(doAnimation);
    });
}

...

this.animateProgress(90, 1000)
    .then(() => {
        if (!this.isCompleted) {
            this.animateProgress(100, 500);
        }
    })
...
复制代码

In this case, add  duration the parameter  animateProgress inside the function and use that parameter to set the animation speed and completion time. When calling the function first, set the playback time of the asynchronous progress bar to 1000ms, so as to obtain the effect of a progress bar with a slower speed and a longer completion time. On the second call to the function, shorten the progress bar completion time to 500ms and get the resulting faster animation.

Summarize

Implementing an interface progress bar function can improve website performance and user experience, and can also make the page more interactive and lively. In Chestnut, the Vue framework is used to build animation components, the Axios interceptor is used to monitor the request progress, and parameter injection is used to control the animation speed and completion time.

Guess you like

Origin blog.csdn.net/weixin_42981560/article/details/130518392