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

Vue2+Vuetify v-stepper切换步骤时如何实现卡片内容自动向上滚动

解决方案

你的滚动逻辑不生效主要是两个原因:

  1. Vue响应式更新slide后,新步骤的DOM渲染是异步的,直接调用滚动方法时目标节点还没挂载完成
  2. Vuetify的v-stepper切换步骤自带300ms左右的过渡动画,动画未完成时滚动位置计算会出错

具体修改步骤:

  1. 给循环渲染的v-card绑定动态ref,方便获取对应步骤的DOM节点
  2. 监听slide变量的变化,等DOM更新+过渡动画完成后再执行滚动逻辑
  3. 修正v-stepper-content的key值,避免因key重复引发的渲染异常

修改后的完整代码:

<template>
  <v-stepper v-model="slide" flat vertical>
    <template v-for="(method, index) in methods">
      <v-stepper-step
        color="#7eba24"
        :complete="slide > index + 1"
        :step="index + 1"
        :key="index"
        @click="slide = index + 1"
      >
        <div class="font-weight-medium cursor-pointer ml-4">
          {{ method.step }}
        </div>
      </v-stepper-step>

      <v-stepper-content :step="index + 1" :key="method.id">
        <!-- 绑定动态ref方便获取DOM -->
        <v-card 
          elevation="5" 
          class="ma-3 scrollY" 
          height="100%"
          :ref="`stepCard_${index + 1}`"
        >
          <v-col>
            <v-row class="pa-5">
              <v-col class="my-auto">
                <v-img
                  class="mx-auto"
                  max-width="230"
                  :src="require(`../assets/methods/${method.img}.png`)"
                ></v-img>
              </v-col>
              <v-col>
                <p class="text-justify">
                  {{ method.desc }}
                </p>
              </v-col>
            </v-row>
          </v-col>
          <v-row class="ma-3 pr-4 pb-5">
            <v-spacer></v-spacer>
            <v-btn
              class="text-capitalize"
              text
              @click="slide -= 1"
              :disabled="slide == 1"
              >Zurück
            </v-btn>

            <v-btn
              class="text-capitalize"
              color="#7eba24"
              @click="slide += 1"
              :disabled="slide == 12"
            >
              Weiter
            </v-btn>
          </v-row>
        </v-card>
      </v-stepper-content>
    </template>
  </v-stepper>
</template>
<script>
export default {
  data() {
    return {
      slide: 1,
      methods: [
        {
          step: "Lorem 1",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 1,
        },
        {
          step: "Lorem 2",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 2,
        },
        {
          step: "Lorem 3",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod ne neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 3,
        },
        {
          step: "Lorem 4",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 4,
        },
        {
          step: "Lorem 5",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 5,
        },
        {
          step: "Lorem 6",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 6,
        },
        {
          step: "Lorem 7",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 7,
        },
        {
          step: "Lorem 8",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 8,
        },
        {
          step: "Lorem 9",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod ne ne ne ne ne ne ne ne ne ne ne ne ne ne ne ne ne",
          img: "dummy",
          id: 9,
        },
        {
          step: "Lorem 10",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 10,
        },
        {
          step: "Lorem 11",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 11,
        },
        {
          step: "Lorem 12",
          desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam placerat ullamcorper nulla. Maecenas tristique dignissim porta. Vestibulum laoreet ante sed vestibulum tincidunt. Nam euismod euismod neque ac mollis. Aliquam ac libero diam. Vivamus vitae enim imperdiet est vestibulum auctor vel eu odio. Nunc vitae sodales ipsum.",
          img: "dummy",
          id: 12,
        },
      ],
    };
  },
  watch: {
    // 监听步骤变化自动执行滚动
    slide(newStep) {
      this.$nextTick(() => {
        // 300ms适配vuetify stepper默认过渡时长,可根据实际效果调整
        setTimeout(() => {
          const targetCard = this.$refs[`stepCard_${newStep}`]?.[0]?.$el
          if(!targetCard) return
          // 若为卡片内部滚动,使用以下代码
          targetCard.scrollTop = 0
          // 若需要页面整体滚动到卡片顶部,替换为以下代码即可
          // targetCard.scrollIntoView({ behavior: 'smooth', block: 'start' })
        }, 300)
      })
    }
  }
};
</script>
<style scoped>
.cursor-pointer {
  cursor: pointer;
}
/* 确保滚动容器样式生效 */
.scrollY {
  overflow-y: auto;
}
</style>

可选调整项:

  • 如果不需要平滑滚动,可以去掉scrollIntoView的behavior: 'smooth'配置,也可以把setTimeout的时长改为0
  • 如果你的项目中自定义过stepper的过渡时长,调整setTimeout的毫秒数和你的过渡时长匹配即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:36:02