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
相关产品推荐
相关产品推荐

