Error in mounted hook: “TypeError: Cannot read property ‘XXXXX‘ of undefined“

在使用Vue的iview组件时,遇到一个TypeError错误:'TypeError: Cannot read property 'initData' of undefined'。问题出在一个有v-if的控件上,移除或更改v-if为v-show解决了问题。原因可能是v-if在DOM未渲染完成时执行,导致引用undefined。理解v-if和v-show的差异对于避免此类错误至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天使用iview画页面时遇到一个很简单但是搞了很久的bug,加了一个控件

<user-select
 style="width:200px"
 @on-change="handleSelect"
 ref="user"
 v-model="form.userCode">
</user-select>

然后使用$refs调用组件属性

this.$refs.user.initData();

然后神奇的地方出现了,不管怎么该,一直报Error in mounted hook: "TypeError: Cannot read property 'initData' of undefined"错误,这个方法之前一直用的呀,各种猜想为啥在这里不行了。

最后发现一件神奇的事情,这个组件换个位置就可以正常工作了,然后放回原处就不行了,然后我想,难道这是iview的bug,某两个控件不能紧跟着放在一起?然后又转过头来想,不可能呀,整个vue生态都这么成熟了,不应该会存在这么低级的错误呀!

然后突然发现,这个控件是所在的位置多了一个v-if判断,难道是因为渲染的顺序导致的?

<Row :gutter="32" v-if="type=='2'">
 <Col span="12>
    <FormItem label="用户选择" prop="userCode" >
        <user-select
          style="width:200px"
          @on-change="handleSelect"
          ref="user"
          v-model="form.userCode">
        </user-select>
    <FormItem>
 </Col>
<Row>

突然感觉像发现新大陆一样欣喜若狂,果然删掉了v-if属性之后能够正常工作了。

然后想应该是vue的加载渲染机制有关,优先渲染html代码,此时js代码还没有执行,所以动态属性还没有值,因此被v-if包裹的代码块没有被封装,此时执行js初始化代码的时候,调ref组件自然是undefined的。

大胆这么才想后,继续实验猜想,如果真像想的那样,那按照v-if和v-show的区别,v-show会在加载html的时候加载完整代码,只是不展示,那这样的话,执行js代码的时候,组件应该是存在的。所以尝试将v-if改成v-show,果然代码执行成功了。

另一起再回顾一下v-if和v-show的区别:

  • 手段:v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏;
  • 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
  • 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译(编译被缓存?编译被缓存后,然后再切换的时候进行局部卸载); v-show是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且DOM元素保留;
  • 性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;

基于以上区别,因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值