[Vue 警告]:nextTick 中的错误:“NotFoundError:无法在 'Node' 上执行 'insertBefore'

Posted

技术标签:

【中文标题】[Vue 警告]:nextTick 中的错误:“NotFoundError:无法在 \'Node\' 上执行 \'insertBefore\'【英文标题】:[Vue warn]: Error in nextTick: "NotFoundError: Failed to execute 'insertBefore' on 'Node'[Vue 警告]:nextTick 中的错误:“NotFoundError:无法在 'Node' 上执行 'insertBefore' 【发布时间】:2019-01-10 04:46:56 【问题描述】:

我偶尔会在我的 Vue Web 应用程序中收到以下错误消息,但当它确实发生时,它会完全停止我的应用程序。

错误信息 1:

[Vue 警告]:nextTick 中的错误:“NotFoundError:执行失败 'Node' 上的 'insertBefore':新节点所在的节点 插入的不是该节点的子节点。”

错误信息 2:

DOMException: 无法在 'Node' 上执行 'insertBefore': 节点 要插入的新节点之前不是 this 的子节点 节点。

错误消息 1 的堆栈跟踪:

错误消息 2 的堆栈跟踪:

根据堆栈跟踪,我已经确定我的仪表板组件中的 setListingFromCoords() 方法导致了问题。问题也不在于 vuex "getListingsFromCoords" 操作,因为 "data" 是 console.logged 正确的信息。此外, data.results 也被正确填充。 根据堆栈跟踪的问题是this.listings = data.results

下面是我的 setListingFromCoords() 方法,它位于仪表板组件中:

setListingFromCoords() 
    return new Promise((resolve, reject) => 
        this.$store.dispatch(
            "getListingsFromCoords"
        ).then((data) => 
            console.log(data); // "data" is returned correctly here
            this.listings = data.results; // CODE BREAKS HERE
            this.previous = data.previous;
            this.hasPrevious = data.hasPrevious;
            this.next = data.next;
            this.hasNext = data.hasNext;
            resolve();
        ).catch((err) => 
            reject(err);
        );
    );
,

在我的仪表板组件的模板部分中,我有以下卡片组件,它是基于上述 setListingFromCoords 方法返回的列表数量的 v-for'ed。这是唯一依赖 listings 的组件,这让我相信这部分会以某种方式导致 Vue 抛出错误。

<card
    v-for="(listing, index) in listings"
    v-bind:index="index"
    v-bind:key="listing._id">
</card>

有人可以确认我的结论是否合理/正确。另外,我该如何修改我的代码来解决这个问题?为什么会抛出这个错误?

【问题讨论】:

【参考方案1】:

我在vue-router 遇到了类似的问题,结果我将&lt;router-view /&gt; 包装在vue-fragment 中。

编辑

这个问题是在vue-fragment v1.5.2 中引入的,请将包降级到 v1.5.1。

正如@jai-kumaresh 提到的,在 package.json "vue-fragment": "^1.5.1" 中删除 ^,这样 npm 将只安装完全相同的版本。

编辑2021 年 10 月

如果您使用的是 Vue 3,则不再需要

vue-fragment 包,现在您可以直接向根元素添加多个元素。 有关该主题的更多信息,请查看 Vue3 指南中的 fragments 部分。

【讨论】:

1.删除 package.json 中的 ^ "vue-fragment": "^1.5.1", 2。然后再次运行 npm i 只有vue-fragment 1.5.1 更新以上的包才会发生这种情况。 谢谢你,你在两个项目中救了我的命:D 有没有跟进为什么这个包更新引入了这个问题?【参考方案2】:

以下内容来自 VueJS 核心团队成员@LinusBorg:

错误消息本身是 Vue 尝试插入的 DOM 异常 一个元素在另一个元素之前,但该元素不再存在 在 DOM 中。

结合您提供的信息,我认为 Vue 尝试在 DOM 中的另一个元素之前插入一个元素 先前由 v-for 创建 - 换句话说,Vue 试图 用它认为的变化修补现有的元素列表 必须反映列表中的更改,并且失败,

我看不到任何直接导致此错误的东西,我唯一的怀疑 是不是你有重复的listing._id?

他的怀疑是正确的。我的仪表板组件中有一个重复的键,这导致了错误。

【讨论】:

不是最初的问题提问者的情况,但如果其他人遇到这个问题,因为它是一个流行的错误。如果你不是在声明一个 v-else 而是连续两个 v-if,它也可能发生!!!【参考方案3】:

我在使用 Vue Slick 滑块时遇到了类似的问题:在我的情况下,解决方案是用 v-show 指令替换组件周围的 v-if 指令。一开始我还删除了生成幻灯片的循环中的:key,但最后我能够再次使用这些键。

【讨论】:

【参考方案4】:

我也遇到了同样的问题。

参与者:我自己的个人资料表单组件+youtube component。

<youtube
    v-if="profileData.showYoutube && profileData.youtubeUrl"
    :video-id="$youtube.getIdFromUrl(profileData.youtubeUrl)"
/>

问题:如果用户查看一些加载了 youtube 组件的个人资料,然后通过点击“创建个人资料”,用户会被vue-routersite.com/some_profile_name 重定向到site.com/create_profile。作为一个额外的步骤profileData 被清理(因为用户想要创建一个新的配置文件......)。

在这种情况下,两个组件都被重用了,但 youtube 出于某种原因,因为 profileData 清理是问题的根源:[Vue warn]: Error in nextTick: "NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node."

解决方案:我能够通过用&lt;div&gt; 包装youtube 组件来修复它(&lt;template&gt; 也会产生错误):

<div v-if="profileData.showYoutube && profileData.youtubeUrl">
    <youtube :video-id="$youtube.getIdFromUrl(profileData.youtubeUrl)"/>
</div>

【讨论】:

【参考方案5】:

我们在使用带有 v-if 的 &lt;template&gt; 元素时看到了这个错误。

如果我们转换为&lt;div&gt;,它似乎可以修复它。

它最终会浪费一点 html,但它确实解决了问题。

【讨论】:

这也是我遇到的问题。在我将我的内部 &lt;template&gt; 标签交换为 &lt;div&gt; 之后,它似乎也解决了这个问题 thx【参考方案6】:
    从 vue-fragment 版本 1.52 降级到版本 1.51 并且不要在版本上添加 ^,现在坚持使用 1.51,因为错误在版本 1.52 上

2.如果你仍然有这个问题尝试删除片段标签周围

所以而不是:

<template>
   <fragment><router-view></router-view></fragment>
</template>

简单地说:

<template>
    <router-view></router-view> 
</template>

或者如果你可以只用其他html标签包装这个路由器视图而不是

内部的组件仍然可以使用

【讨论】:

以上是关于[Vue 警告]:nextTick 中的错误:“NotFoundError:无法在 'Node' 上执行 'insertBefore'的主要内容,如果未能解决你的问题,请参考以下文章

关于vue中的nextTick深入理解

vue中的$nextTick()

从Vue.nextTick探究事件循环中的线程协作机制

vue中的this.$nextTick().then()

Vue中的nextTick

聊聊VUE中的nextTick