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

如何在v-lazy组件中正确使用$vuetify.goTo?

问题根源

  1. 组件未完全渲染就触发定位:$nextTick仅等待DOM结构更新,但移动端高高度组件(如Projects)内的图片、动态内容加载需要额外时间,此时元素实际高度未计算完成,$vuetify.goTo基于占位高度定位,自然出现偏差。
  2. v-lazy占位高度配置错误:contact项的min-height缺少单位(需写成'300px'),且移动端50vh的占位远小于组件实际的150-200vh,导致滚动位置计算错误。
  3. 定位触发时机过早:刚设置isActive就立刻执行跳转,未等待组件内部内容渲染到位。

解决方案

1. 修正v-lazy基础配置

确保占位高度匹配组件实际尺寸,单位统一,同时调低阈值让组件更早加载:

<v-lazy 
  v-for="item in items" 
  :key="item.component" 
  :id="item.component" 
  v-model="item.isActive"
  :options="{ threshold: 0 }"  <!-- 阈值设0,组件一进入视口就加载 -->
  :min-height="item.component === 'contact' ? '300px' : '200vh'"  <!-- 匹配移动端组件实际高度范围 -->
>
  <v-component :is="item.component" />  <!-- 注意:原代码拼写错误*v-componenet* → *v-component* -->
</v-lazy>

2. 优化跳转方法,等待组件完全渲染

不要仅依赖$nextTick,添加小延迟确保图片等内容加载完成后再执行定位:

methods: {
  async goToItem(destination) {
    // 激活目标组件及所有前置组件
    const targetIndex = this.items.findIndex(i => i.component === destination);
    this.items.forEach((item, index) => {
      if (index <= targetIndex) {
        item.isActive = true;
      }
    });

    // 先等DOM更新,再预留时间让内容加载(可根据实际情况调整延迟时长)
    await this.$nextTick();
    await new Promise(resolve => setTimeout(resolve, 300));

    // 执行跳转,添加动画时长适配滚动
    this.$vuetify.goTo(`#${destination}`, {
      duration: 500,
      offset: 0  // 若有固定导航栏,此处需设置导航栏高度,如64
    });
  }
}

3. 精准监听组件加载完成(可选,更可靠)

如果组件包含大量图片或异步内容,让子组件主动通知父组件加载完成:

  • 子组件示例(如Projects.vue):
<script>
export default {
  mounted() {
    const imgs = this.$el.querySelectorAll('img');
    let loadedCount = 0;

    // 统计已加载的图片
    imgs.forEach(img => {
      if (img.complete) loadedCount++;
    });

    // 给未加载的图片添加监听
    imgs.forEach(img => {
      if (!img.complete) {
        img.addEventListener('load', () => {
          loadedCount++;
          if (loadedCount === imgs.length) this.$emit('loaded');
        });
      }
    });

    // 无图片时直接通知加载完成
    if (imgs.length === 0) this.$emit('loaded');
  }
};
</script>
  • 父组件监听并等待所有必需组件加载完成后再跳转:
<template>
  <v-lazy ...>
    <v-component 
      :is="item.component" 
      @loaded="markComponentLoaded(item.component)"
    />
  </v-lazy>
</template>

<script>
export default {
  data() {
    return {
      // ...
      loadedComponents: new Set()  // 存储已加载完成的组件名
    };
  },
  methods: {
    markComponentLoaded(component) {
      this.loadedComponents.add(component);
    },
    async goToItem(destination) {
      const targetIndex = this.items.findIndex(i => i.component === destination);
      const requiredComponents = this.items.slice(0, targetIndex + 1).map(i => i.component);
      
      // 激活所有必需组件
      requiredComponents.forEach(comp => {
        const item = this.items.find(i => i.component === comp);
        if (item) item.isActive = true;
      });

      // 等待所有必需组件加载完成
      await new Promise(resolve => {
        const checkLoaded = () => {
          const allDone = requiredComponents.every(comp => this.loadedComponents.has(comp));
          if (allDone) resolve();
          else setTimeout(checkLoaded, 100);
        };
        checkLoaded();
      });

      // 执行定位
      this.$vuetify.goTo(`#${destination}`);
    }
  }
};
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:30:52