跳至主要內容

Vue3 中使用 fake-progress 模拟“真实”的进度条

Bing🐣2023年6月24日VueVue3VueVue3fake-progress大约 3 分钟

Vue3 中使用 fake-progress 模拟“真实”的进度条

最近在逛 GitHub 的过程中发现一个很有趣的库,fake-progress,用来模拟“真实”的进度条,虽然看着已经很多年没更新了,但是不妨碍在 Vue3 中集成使用,这样就不用手搓模拟进度条了,在页面加载顶部进度条、文件上传进度条等等很有用处。

安装 fake-progress

使用自己常用的方式安装fake-progress即可。

npm
npm install fake-progress

Vue2 中使用

在 Vue2 中使用非常简单,直接通过new FakeProgress创建实例后即可在模版中使用fake.progress,获取百分比数值可以通过parseInt

<template>
  <div>
    <div>{{ fake.progress }}</div>
    <div>{{ percentage }}</div>
  </div>
</template>

<script>
import FakeProgress from 'fake-progress'
export default {
  data() {
    return {
      fake: new FakeProgress({
        timeConstant: 5000,
        autoStart: true
      })
    }
  },
  computed: {
    percentage() {
      return parseInt(this.fake.progress * 100)
    }
  }
}
</script>
image
image

Vue3 中使用

按同样的方法,引入包后通过new FakeProgress创建一个实例,页面绑定fake.progress后发现显示的一直是 0,数据也没任何变化。通过查看该库的源码可以知道数值的变化是通过setInterval设置的,而且间隔也是固定的 100:this._intervalFrequency = 100;

<template>
  <div>
    {{ fake.progress }}
  </div>
  <div>
    {{ percentage }}
  </div>
</template>

<script setup lang="ts">
import FakeProgress from 'fake-progress'
import { computed } from 'vue'

const fake = new FakeProgress({
  timeConstant: 5000,
  autoStart: true
})
const percentage = computed(() => parseInt(fake.progress * 100 + ''))
</script>

setInterval 改造

我们也加一个同样的setInterval去间隔读取fake.progress

<template>
  <div>
    {{ progress }}
  </div>
  <div>
    {{ percentage }}
  </div>
</template>

<script setup lang="ts">
import FakeProgress from 'fake-progress'
import { ref, computed } from 'vue'

const fake = new FakeProgress({
  timeConstant: 5000,
  autoStart: true
})
const progress = ref(fake.progress)
const percentage = computed(() => parseInt(progress.value * 100 + ''))
setInterval(() => {
  progress.value = fake.progress
}, 100)
</script>

搭配 UI 组件使用

可以搭配一些 UI 的进度条组件或者顶部进度条的组件使用,下面以Element PlusProgress 进度条组件为例子,在需要结束进度条的时候调用FakeProgress实例提供的end()方法即可。

<template>
  <div>
    <el-progress
      :percentage="percentage"
      :striped="true"
      :striped-flow="true"
    />
  </div>
  <div>
    <el-progress type="circle" :percentage="percentage" />
  </div>
  <div>
    <el-button type="danger" @click="fake.end()">结束</el-button>
  </div>
</template>
image
image

封装成 Hook

为了方便日常使用,我们可以封装一个useFakeProgress的 Hook,引入后直接可以使用percentage和相关的start()end()方法。

Demo.vue
<template>
  <div>
    <el-progress
      :percentage="percentage"
      :striped="true"
      :striped-flow="true"
    />
  </div>
  <div>
    <el-progress type="circle" :percentage="percentage" />
  </div>
  <div>
    <el-button type="primary" @click="start()">开始</el-button>
    <el-button type="danger" @click="end()">结束</el-button>
  </div>
</template>

<script setup lang="ts">
import { useFakeProgress } from '@/hooks/useFakeProgress'

const fakeProgress = useFakeProgress()
const percentage = fakeProgress.percentage
const { start, end } = fakeProgress
</script>
image
image

TS 申明

最后将 TS 申明加入到项目的env.d.ts或者其他申明类型的d.ts中。

interface FakeProgressOptions {
  timeConstant: number
  autoStart?: boolean
  parent?: FakeProgress
  parentStart?: number
  parentEnd?: number
}

declare module 'fake-progress' {
  export = FakeProgress

  class FakeProgress {
    constructor(opts: FakeProgressOptions)

    progress: number

    createSubProgress(opts: FakeProgressOptions): FakeProgress

    end(): void

    setProgress(progress: number): void

    start(): void

    stop(): void
  }
}