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

Vue.js方法内访问模板Ref报undefined的解决方法

解决Vue Methods中访问模板Ref返回Undefined的问题

看起来你遇到的问题是在模板绑定的方法里访问$refs时拿到了undefined,这其实是Vue生命周期和DOM渲染时机的问题,我来帮你拆解下原因和解决方案:

为什么会出现Undefined?

Vue的模板ref只有在组件挂载完成后才会被赋值到this.$refs上。而你在模板的:style里直接调用getMileStonePercent,这个函数会在组件首次渲染(还没完成挂载)时就执行,此时this.$refs.lvl1_target还没被初始化,自然会返回undefined。

解决方案

我给你两种常用的处理方式,你可以根据自己的场景选择:

方案一:用Mounted钩子初始化+响应式数据(推荐)

把宽度值存在响应式data里,等组件挂载完成(DOM已渲染,ref可用)后再计算赋值,模板直接用这个数据,避免在渲染阶段调用方法访问未就绪的ref:

<template>
  <ul ref="lvl1_target" style="width: 440px" class="lvl1_target milestone_asset_data">
    <li :style="{'width': lvl1Width}" class="hybse_data">
      <span></span>
      <i></i>
      <small>$4M</small>
    </li>
  </ul>
</template>

<script>
export default {
  data() {
    return {
      lvl1Width: '0%' // 默认值
    }
  },
  methods: {
    getMileStonePercent(num, secWrp) {
      const ele = this.$refs[secWrp]
      // 这里假设你是要按num/4的比例计算宽度,可根据实际需求调整逻辑
      return ele ? `${ele.offsetWidth * (num / 4)}%` : '0%'
    }
  },
  mounted() {
    // 组件挂载完成后,ref已经可用,计算并赋值
    this.lvl1Width = this.getMileStonePercent(4, 'lvl1_target')

    // 如果需要监听窗口 resize 实时更新宽度
    const updateWidth = () => {
      this.lvl1Width = this.getMileStonePercent(4, 'lvl1_target')
    }
    window.addEventListener('resize', updateWidth)

    // 组件销毁时移除监听,防止内存泄漏
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener('resize', updateWidth)
    })
  }
}
</script>

方案二:方法内判断+NextTick异步更新(适合动态渲染场景)

如果你的ref元素是动态显示的(比如有v-if控制),可以在方法里先检查元素是否存在,不存在就用$nextTick异步获取并更新:

<template>
  <ul ref="lvl1_target" style="width: 440px" class="lvl1_target milestone_asset_data">
    <li :style="{'width': currentWidth}" class="hybse_data">
      <span></span>
      <i></i>
      <small>$4M</small>
    </li>
  </ul>
</template>

<script>
export default {
  data() {
    return {
      currentWidth: '0%'
    }
  },
  methods: {
    getMileStonePercent(num, secWrp) {
      const ele = this.$refs[secWrp]
      if (ele) {
        const width = `${ele.offsetWidth * (num / 4)}%`
        this.currentWidth = width
        return width
      } else {
        // 元素还没渲染,等DOM更新后再重新计算
        this.$nextTick(() => {
          this.getMileStonePercent(num, secWrp)
        })
        return this.currentWidth
      }
    }
  },
  mounted() {
    // 初始化调用一次
    this.getMileStonePercent(4, 'lvl1_target')
  }
}
</script>

额外注意点

  • 绝对不要在created钩子中访问模板ref,此时DOM还没生成,ref肯定是undefined。
  • 如果ref是在v-for里生成的,this.$refs[secWrp]会是一个数组,需要遍历处理。
  • 监听窗口resize时一定要记得在组件销毁时移除监听,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:13:44