You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

vue3-steppy基于API动态生成步骤时的步号动态更新问题

Fix: Dynamic Step Number Sync in vue3-steppy

Root Cause

vue3-steppy’s default step numbering relies on the initial step array’s index. When you dynamically update steps via API, the component doesn’t recalculate the current step’s position in the new list, leading to mismatched step numbers (like showing #1 when you’re actually on the second dynamic step).

Solutions

Override the step title slot to manually calculate and display the correct step number, instead of relying on the component’s internal index:

<template>
  <vue3-steppy
    :steps="dynamicConflictSteps"
    :active-step="currentStepIdx"
    @next="goToNextStep"
    @prev="goToPrevStep"
  >
    <!-- Custom step title with dynamic number -->
    <template #step-title="{ step }">
      #{{ getStepPosition(step) }} {{ step.conflictType }}
    </template>

    <!-- Step content -->
    <template #content="{ step }">
      <ConflictResolver :conflict="step" />
    </template>
  </vue3-steppy>
</template>

<script setup>
import { ref } from 'vue'
import Vue3Steppy from 'vue3-steppy'
import 'vue3-steppy/dist/vue3-steppy.css'
import ConflictResolver from './components/ConflictResolver.vue'

const dynamicConflictSteps = ref([])
const currentStepIdx = ref(0)

// Fetch conflict data from API
const loadConflictSteps = async () => {
  const response = await fetch('/api/conflicts')
  const conflictData = await response.json()
  // Map API data to step format
  dynamicConflictSteps.value = conflictData.map(conflict => ({
    conflictType: conflict.type,
    ...conflict
  }))
}

// Calculate current step's 1-based number
const getStepPosition = (step) => {
  return dynamicConflictSteps.value.indexOf(step) + 1
}

// Navigation handlers
const goToNextStep = () => {
  if (currentStepIdx.value < dynamicConflictSteps.value.length - 1) {
    currentStepIdx.value++
  }
}

const goToPrevStep = () => {
  if (currentStepIdx.value > 0) {
    currentStepIdx.value--
  }
}

// Initialize on mount
loadConflictSteps()
</script>

2. Force Component Re-render (Quick Fix)

If custom numbering isn’t feasible, trigger a full re-render of vue3-steppy when steps update by changing its key prop. This resets the component’s internal state to match the new step list:

<template>
  <vue3-steppy
    :key="stepListKey"
    :steps="dynamicConflictSteps"
    :active-step="currentStepIdx"
    @next="goToNextStep"
    @prev="goToPrevStep"
  >
    <!-- Step content here -->
  </vue3-steppy>
</template>

<script setup>
import { ref } from 'vue'
import Vue3Steppy from 'vue3-steppy'

const dynamicConflictSteps = ref([])
const currentStepIdx = ref(0)
const stepListKey = ref(0)

const loadConflictSteps = async () => {
  const response = await fetch('/api/conflicts')
  const conflictData = await response.json()
  dynamicConflictSteps.value = conflictData.map(conflict => ({
    title: conflict.type,
    content: conflict
  }))
  // Increment key to force re-render
  stepListKey.value++
}
</script>

3. Guard Against Index Out-of-Bounds

If steps can be added/removed dynamically, add a watcher to keep the current step index within valid bounds:

import { watch } from 'vue'

watch(dynamicConflictSteps, (newSteps) => {
  if (currentStepIdx.value >= newSteps.length) {
    currentStepIdx.value = newSteps.length > 0 ? newSteps.length - 1 : 0
  }
}, { deep: true })

Notes

  • Custom numbering is the most robust approach—it gives you full control over step number logic, regardless of component internals.
  • The key-based re-render works for simple cases but may reset any unsaved state in step components (like form inputs), so use it cautiously.
  • The watcher prevents errors if the step list shrinks while the user is on a step that no longer exists.

内容的提问来源于stack exchange,提问作者Pave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:00:57