【问题标题】:[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>

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

【问题讨论】:

    标签: javascript debugging vue.js vuejs2 vue-component


    【解决方案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】:
        1. 从 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标签包装这个路由器视图而不是

        内部的组件仍然可以使用

        【讨论】:

          猜你喜欢
          • 2022-11-30
          • 1970-01-01
          • 2020-12-09
          • 2019-06-01
          • 2019-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-01
          相关资源
          最近更新 更多