可能的原因:
1.检查无效的html标签,比如<p><p></p>等,尽量使用<p></p> 而非<p/>
2.改变 HTML 的脚本.如果您已将第三方 javascript 文件添加到您的 Vue 应用程序中,这些文件也可能会在 Vue 接管并合并来自服务器的 HTML 之前更改 HTML(例如通过嵌入表单)
3.服务器和客户端上的状态不同是水合的最常见原因。与往常一样,不一致的原因可能多种多样
4.日期、时间戳和随机化 .当您在网站上包含日期或时间戳时,您应该小心并尽可能使其静态,特别是如果您的网站是静态生成的。如果客户端计算类似的表达式,new Date()则它可能与部署期间检索相同日期时在服务器上生成的日期不同。
5.auth认证:当仅在客户端(例如本地存储)存储身份验证状态时,服务器“不知道身份验证”。这将不可避免地导致水合问题,因为当您登录时,服务器和客户端信息根本不同。因此,如果服务器不知道身份验证状态或您的身份验证状态,则不应在服务器端渲染任何与身份验证相关的组件。
以上只是一些比较常见的情况,还有更多的边缘情况可能会影响您并导致不一致。这里没有列出,具体什么问题导致的取决于你的代码的书写情况。
6.最终解决方案:使用<client-only>(version需>2.9) or <no-ssr>标签包裹组件(ps: 脚本中可判断process.client or process.browser是否为浏览器端)。唯一的缺点:该组件不包含在服务器返回的 HTML 中,对 SEO 没有帮助。
解决:
ps: 我遇到的问题是如下结构中,不能保留注释:
{ { isAllCompReady }}
<!-- 如此这样也会导致水合出错,删除此注释即可fix -->
<div class="box_absolute" ></div>
还有就是v-if也可能影响,需将v-if 改为v-show
快速定位水合报错的组件:
这个错误调试起来真的很痛苦。
1.为了快速获取导致问题的元素,可以编辑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)
// ...
这样可在控制台中看到出现故障的节点。
2.还有一种方式,可快速定位错误元素
确保您处于开发模式
打开 DevTools(通常按 F12)
触发水合警告(通常通过重新加载网站)
展开[Vue Warn] The client side ...错误消息以查看堆栈跟踪(根据浏览器,还可以展开弹出的“VueJS”列表)
单击其中一个hydrate 调用。这将打开Vue的水合功能的源代码。
现在,只要函数返回,就设置一个调试器false。到撰写本文时,这种情况发生了三次:
if (process.env.NODE_ENV !== 'production') {
if (!assertNodeMatch(elm, vnode, inVPre)) {
return false //HERE
}
}
if (process.env.NODE_ENV !== 'production' &&
typeof console !== 'undefined' &&
!hydrationBailed
) {
hydrationBailed = true;
console.warn('Parent: ', elm);
console.warn('server innerHTML: ', i);
console.warn('client innerHTML: ', elm.innerHTML);
}
return false //HERE
}
if (process.env.NODE_ENV !== 'production' &&
typeof console !== 'undefined' &&
!hydrationBailed
) {
hydrationBailed = true;
console.warn('Parent: ', elm);
console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children);
}
return false //HERE
}
这使我们能够在水合失败之前检查水合函数的参数
最后但并非最不重要的一点是,让水合错误再次出现。通常,可以通过重新加载页面来实现这一点,但有时会更困难。
您现在看到我们的断点之一被触发并且脚本执行被停止
现在打开 DevTool 的控制台并写入elm以获取水合作用失败的 DOM 元素。使用 DOM 元素,您应该能够将水合错误追溯到 Vue 组件之一
继续执行后续步骤