Vuejs错误:客户端呈现的虚拟DOM树与服务器呈现不匹配

asa*_*nas 10 javascript vue.js vuejs2 nuxt.js

我正在使用Nuxt.js/Vuejs for mmy app,我在不同的地方一直面临这个错误:

    The client-side rendered virtual DOM tree is not matching server-rendered content. 
This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. 
Bailing hydration and performing full client-side render.
Run Code Online (Sandbox Code Playgroud)

我想了解调试此错误的最佳方法是什么?他们是否可以为客户端和服务器记录/获取虚拟DOM树,以便我可以比较并找到错误所在的位置?

我的是一个大型应用程序,并且手动验证很困难.

bud*_*n73 42

部分答案:使用Chrome DevTools,您可以本地化问题并确切了解导致问题的元素.执行以下操作(我使用Nuxt 5.6.0和Chrome 64.0.3282.186执行此操作)

  1. 在Chrome中显示DevTools(F12)
  2. 加载导致"客户端呈现的虚拟DOM树..."警告的页面.
  3. 滚动到DevTools控制台中的警告.
  4. 单击警告的源位置超链接(在我的例子中,它是vue.runtime.esm.js:574).
  5. 在那里设置断点(在源代码浏览器中左键单击行号).
  6. 使相同的警告再次出现.我并不是说它总是可行的,但就我而言,我只是重新加载页面.如果有许多警告,您可以通过将鼠标移到msg变量上来检查消息.
  7. 当您找到消息并在断点处停止时,请查看调用堆栈.单击一帧向下调用"patch"以打开其源.将鼠标悬停hydrate在执行行上方4行的函数调用中patch.超链接到源hydrate将打开.
  8. hydrate函数中,从开始移动大约15行并设置断点,false返回后assertNodeMatch返回false.在那里设置断点并删除所有其他断点.
  9. 再次发出相同的警告.现在,当命中断点时,执行应该在hydrate函数中停止.切换到DevTools控制台和评估elm,然后vnode.这里elm似乎是一个服务器呈现的DOM元素,而vnode是一个虚拟DOM节点.Elm以HTML格式打印,因此您可以找出错误发生的位置.

  • +1000教我如何正确使用断点! (7认同)
  • “ Nuxt 5.6.0”,您生活在未来吗? (6认同)
  • 访问 hydr 函数执行的一种更快的方法是在 Chrome 开发工具的控制台区域中展开错误,您可以在列表中看到它。只需单击同一行的@ 符号后面的链接。例如水合物@ commons.app.js:15934 (4认同)
  • 我发现这个博客根据 @budden73 的回答发布了这个错误的扩展解释,它实际上帮助我理解了这个问题。希望这可以帮助其他人:https://blog.lichter.io/posts/vue-Hydration-error/ (4认同)

kis*_*ssu 22

有很多方法可以解决这个问题,但其中大多数都不是真正的解决方案,只是简单的创可贴。要注意几点:

  • 将其包装到标签中,但<client-only>要注意一些重要的细节
  • 使用 av-show代替 av-if
  • 试图破解一些生命周期
  • ETC...

我强烈推荐阅读 Alexander Lichter 撰写的这篇精彩文章

https://blog.lichter.io/posts/vue-Hydration-error/

他会向您解释,您应该诊断为什么会发生这种情况并解决实际问题。
基本上每次与服务器上生成的内容不同以及在客户端上完成水合作用时可用的内容时都会导致此错误。

其中一些是:

  • 无效的 HTML(在 a 内有一个块元素<p>,嵌套在另一个标签中的标签也是如此a,等等......)
  • 第三方脚本扰乱你的组件
  • 服务器与客户端的不同状态
  • 任何随机都是有风险的(new Date()例如)
  • 与身份验证相关的任何页面

我强烈建议您阅读这篇文章,用 Alexandre 自己的话来了解如何处理此类问题。如果你很着急,你总是可以使用一种创可贴修复,但尝试实际修复问题以获得最佳性能并保持代码干净。


Moh*_*sen 18

对我来说,这个错误发生了,因为获取数组列表AsyncData并渲染<tr>标签v-for,我把v-for代码放在<client-only>块中,问题解决了

  • 如果您不使用 Nuxt,则需要安装 [vue-client-only](https://github.com/egoist/vue-client-only) (3认同)

Fra*_*nci 12

感谢budden73的回答,我对调试过程做了一些改进。

  1. 打开开发工具
  2. 单击warn消息,然后单击警告消息的第一行,您将被引导到Sources面板,带有文件名vue.runtime.esm.js?xxxx

在此输入图像描述

  1. ctrl+f在上面的文件中搜索assertNodeMatch,不是函数,而是类似:
    if (process.env.NODE_ENV !== 'production') {
      if (!assertNodeMatch(elm, vnode, inVPre)) {
        return false
      }
    }
Run Code Online (Sandbox Code Playgroud)
  1. 在该行添加断点return false

在此输入图像描述

  1. 刷新页面,就会触发断点。
  2. 在“源”面板右侧的 下Scope->Local,单击该elm元素,您将被引导回Elements面板。

在此输入图像描述

  1. 上面的元素是client side渲染的元素,与您的代码进行比较以查看差异。

如果你找不到错误的根源,修复它的残酷方法是使用 nuxt 的<client-only>标签。

这里描述了另一种可能的残酷方式。添加一个isHydrate默认为 false 的变量,在mountedhook 中设置为 true,并渲染该变量设置为 true 后的元素。


小智 8

2.14.0在实现vue-particles包时,我遇到了与 nuxt 版本相同的问题。解决方法是用 包围标签no-ssr并解决了问题。

编辑:
解决方案的更新变体(如果 Nuxt 版本高于2.9.0

<client-only>
  <vue-particles>
  </vue-particles>
</client-only>
Run Code Online (Sandbox Code Playgroud)

旧解决方案:

<no-ssr>
  <vue-particles>
  </vue-particles>
</no-ssr>
Run Code Online (Sandbox Code Playgroud)


小智 6

这个错误调试起来真的很痛苦。为了快速获取导致问题的元素,请编辑node_modules/vue/dist/vue.esm.js并添加以下行:

// Search for this line: 
function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
    var i;
    var tag = vnode.tag;
    var data = vnode.data;
    var children = vnode.children;
    inVPre = inVPre || (data && data.pre);
    vnode.elm = elm;

    // Add the following lines: 
    console.log('elm', elm)
    console.log('vnode', vnode)
    console.log('inVpre', inVPre)
    // ...


Run Code Online (Sandbox Code Playgroud)

您将在控制台中获得故障节点。


Hoa*_*ell 6

检查之前的警告:

在 中"nuxt": "^2.12.2",您可以从之前的警告中轻松找出原因。

在此输入图像描述

就我而言:

不正确

<nuxt-link to="/game42day">
  <a>Game For Today</a>
</nuxt-link>
Run Code Online (Sandbox Code Playgroud)

正确的:

<nuxt-link to="/game42day">
  Game For Today
</nuxt-link>
Run Code Online (Sandbox Code Playgroud)


men*_*pet 5

对于 2.10 以上的 Nuxt 版本,它不需要安装任何东西,只需使用<client-only>提到的默认组件https://nuxtjs.org/api/components-client-only/