Skip to content

Progress 进度条 ​

Progress 展示一项任务的完成程度:线性进度条占满容器宽度,圆环按 size 固定直径。它不收用户输入, 值只由数据驱动;父组件也可以调实例方法直接推动进度。

基础用法 ​

默认样式把「已完成」和「剩余」画成两段:中间留一个 4px 的间隙,线性轨道末端还有一个圆点标出剩余部分的终点。

vue
<script setup lang="ts">
import { ref } from "vue";
import { Progress } from "@sharpdotnut/dotsharp";

const value = ref(32);
</script>

<template>
  <Progress :value="value" label="上传进度" />
</template>

value 夹在 0–max(默认 100)之间,非法值按 0 处理。线性进度条厚度固定 4px,宽度由外部(class 或父元素)决定。

变体 ​

variant="continuous" 换成整条背景:轨道不再断开,进度直接叠在完整背景上,也没有末端圆点。

vue
<template>
  <Progress :value="76" label="默认样式" />
  <Progress :value="76" variant="continuous" label="整条背景" />
</template>

圆环 ​

shape="circular" 从 12 点顺时针填充。size 是直径(px,默认 48),圆环粗细取它的 1/12,所以放大时比例保持不变。 默认变体在 12 点和进度点各留一处间隙,continuous 则是一整圈背景加上方的进度弧。

vue
<template>
  <Progress :value="48" shape="circular" label="播放进度" />
  <Progress :value="48" shape="circular" variant="continuous" label="播放进度" />
  <Progress :value="64" shape="circular" :size="72" label="同步进度" />
  <Progress :value="64" shape="circular" variant="continuous" :size="96" label="同步进度" />
</template>

不确定进度 ​

时长未知时用 indeterminate:线性轨道上循环扫过一段实心段,圆环是一段绕圈的弧。此时 value 被忽略, variant 也不再生效——不确定态没有端点,也就没有「留空」可言,两条 / 整圈轨道都原样保留。

vue
<template>
  <Progress indeterminate label="正在处理" />
  <Progress indeterminate shape="circular" label="正在加载" />
  <Progress indeterminate shape="circular" :size="72" label="正在加载" />
</template>

动效来自 src/styles/index.css 里的 --animate-ds-progress-indeterminate(线性)与 Tailwind 自带的 animate-spin(圆环)。两者都带 motion-reduce 退路:系统开启「减少动态效果」时,线性停成一段静止的实心段, 圆环停成一段静止的弧,而不是停在轨道外或整圈空转。

命令式更新 ​

组件实例暴露 setValue(value):值先夹在 0–max 之间,再写回 v-model:value,显示进度沿既有的 300ms 过渡 动到新位置。方法不分形状,线性与圆环是同一个入口;下例两个形状共用同一个绑定值,按钮只调实例方法。

当前值:20

vue
<script setup lang="ts">
import { ref } from "vue";
import { Button, Progress } from "@sharpdotnut/dotsharp";

const progress = ref<InstanceType<typeof Progress> | null>(null);
const ring = ref<InstanceType<typeof Progress> | null>(null);
const random = ref(20);

function randomize() {
  const next = Math.round(Math.random() * 100);
  progress.value?.setValue(next);
  ring.value?.setValue(next);
}
</script>

<template>
  <Progress ref="progress" v-model:value="random" label="随机进度" class="min-w-0 flex-1" />
  <Progress ref="ring" v-model:value="random" shape="circular" :size="64" label="随机进度" />
  <Button @click="randomize">随机更新</Button>
</template>

没有 v-model:value 时,setValue() 写下的值只留在组件内部;父组件传下的 value 再次变化会覆盖它。 不确定态下调用只同步值,视觉不变。

API ​

属性类型默认值说明
v-model:valuenumber0当前进度,夹在 0–max 之间
maxnumber100进度上限
shape"linear" | "circular""linear"线性进度条或圆环
variant"detached" | "continuous""detached"两段留空 / 整条背景
sizenumber48圆环直径(px),粗细取 1/12;线性形状忽略
indeterminatebooleanfalse不确定进度:忽略 value 与 variant
labelstring—无障碍名称
  • 根元素是 role="progressbar",class / style 与其余属性都落在它上面。
  • 圆环按 size 固定尺寸;线性进度条总是占满容器宽度,用 class="w-64" 或父元素收窄。
  • indeterminate 是布尔开关,与 value 同时出现时以它为准。

暴露的方法 ​

方法说明
setValue(value)夹取后写入 value,并发出 update:value

事件 ​

事件说明
update:value值变化(setValue() 写入时发出,供 v-model 同步)

可访问性 ​

根元素带 role="progressbar" 与 aria-valuemin / aria-valuemax / aria-valuenow,aria-valuenow 写入夹住后的值; indeterminate 时这三个属性全部省略,读屏据此报「不确定进度」;label 写成 aria-label。 视觉部分是装饰性的(aria-hidden),读屏只读这个根节点。