亲宝软件园·资讯

展开

vue报错Failed to execute 'appendChild' on 'Node'解决

muio 人气:0

一、问题描述

某天在开发需求时发现,业务页面上报告了一个Script error。

由于vconsole看不到详细报错信息,于是在chrome上打开,具体报错信息如下:

Uncaught DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method. at Object.appendChild 

看起来是vue2.6.12包里报了一个错误,但从报错提供的信息看不出来那行代码引发的报错。

二、解决过程

1、google

解决问题的第一步往往是先看看“别人咋解决的”:把错误信息ctrl+c ctrl+v到浏览器里google一下先。

stackoverflow里看到的第一个解决方案是通过添加client-only标签:

<template>
  <div id="container">
     <client-only>
        <Components>
     </client-only>
  <div>
</template>

在项目里也照着这个方法在App.vue里添加client-only标签,重试后发现没有效果,依然报错。

也有说法说是由于标签的关闭写法导致的Hydration errors

于是我搜索了下项目代码,发现确实有几处标签是使用类似 <span class="split" /> 写法进行关闭的。抱着尝试的心理,我把这些写法都改成了<span class="split"></span>

然而重试后依然没有解决这个报错。

2、断点调试

既然网上的方法没有效果,那只能打断点看看是否能找到报错的具体位置。

从错误报告点击进详情,可以看到是vue.min.js文件的appendChild抛出的错误。

在这里打一个断点,并运行:

第一次经过此处:e是一个div,t是一个#comment的node节点,此时还没有抛出错误。

第二次经过此处:e是一个div,t是一个text元素,此时还没有抛出错误。

第三次经过此处:e是#comment的node节点,t是一个按钮的div元素,此处抛出了对应的错误。

也就是在第三次运行appendChild时,由于e此时是一个node节点,不支持appendChild方法,于是vue抛出了Uncaught DOMException: Failed to execute 'appendChild' on 'Node': This node type does not support this method.错误。

在项目里搜索comment,发现并没有找到相应的代码。于是从第三次appendChild的t参数入手。

可以看出来这是一个按钮元素,并且按钮文字内容是“我知道了”。在项目里搜索“我知道了”,可以找到两处符合条件的元素。根据此时的页面位置可以排除captcha组件,所以锁定了verifyResult组件里的“我知道了”按钮。

这处按钮的html代码如下:

<q-button
  v-if="resultInfo.showBtn"
  type="primary"
  @click="resultInfo.callback"
>
  {{ resultInfo.btnText }}
</q-button>

先把这部分内容直接注释掉看看。 发现这个报错确实不见了。可以确认,这个按钮就是报错的源头。

3、定位

那这个按钮到底有啥问题呢?看起来就是一个平平无奇的确认按钮呀。

从刚刚打断点的时候可以看到,此时按钮的text正常取到了"我知道了"文案,且报错信息是在进行appendChild,也就是添加元素的动作时。而这个按钮里用到了v-if,合理怀疑是这个v-if引起的。于是尝试把v-if去掉或改成一个常量,发现页面也不会报错。

所以可以确定,这里的报错是由于v-if的参数引起的。

这里v-if的参数是:resultInfo.showBtn

这里resultInfo是一个计算参数:

showBtn是通过另一个计算参数:isMobile来控制的。

看来问题就在isMobile上。

通过打印isMobile发现,在node时由于没有window,所以isMobile=false,而页面渲染时isMobile=true。

所以这里isMobile有一个从false -> true的变化。

所以这里按钮元素经历了从无到有的过程,在appendChild的时候node节点就抛出了错误。

4、解决

这里解决方案的主要就是去掉这个从无到有的过程,或者把这个变化后移。

created() {
    this.isMobile = browser.isMobile();
}

两种方法都可以解决,我这里使用了第一种解决方案,报错不再出现,且页面按钮可以正常显示~

加载全部内容

相关教程
猜你喜欢
用户评论