Vuejs 오류:클라이언트측 렌더링된 가상 DOM 트리가 서버에서 렌더링된 트리와 일치하지 않음
내 앱에 Nuxt.js / Vuejs를 사용하고 있는데, 계속 다른 곳에서 이 오류가 발생하고 있다.
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.
이 오류를 디버깅하는 가장 좋은 방법이 무엇인지 알고 싶다.오류가 있는 위치를 비교하고 찾을 수 있도록 클라이언트 및 서버의 가상 DOM 트리를 기록/획득하는 방법인가?
내 것은 큰 어플리케이션이고 수작업으로 검증하는 것은 어렵다.
부분 답변: Chrome DevTools를 사용하여 문제를 로컬로 만들고 문제의 원인이 무엇인지 정확하게 확인할 수 있다.다음을 수행하십시오(Nuxt 5.6.0 및 Chrome 64.0.3282.186으로 수행).
- 크롬으로 DevTools 표시(F12)
- 클라이언트측 렌더링된 가상 DOM 트리가 발생하는 페이지를 로드하십시오.경고.
- DevTools 콘솔에서 경고로 스크롤하십시오.
- 경고의 소스 위치 하이퍼링크를 클릭하십시오(내 경우 vue.runtime.esm.js:574).
- 여기서 중단점을 설정하십시오(소스 코드 브라우저에서 라인 번호를 왼쪽 클릭).
- 동일한 경고를 다시 표시하십시오.나는 그것이 항상 가능하다고 말하는 것은 아니지만, 내 경우에는 단순히 페이지를 다시 로드했다.경고가 많으면 마우스를 위로 이동하여 메시지를 확인할 수 있다.
msg
가변의 - 메시지를 발견하고 중단점에 멈추면 통화 스택을 보십시오.소스를 열려면 "패치"로 호출하려면 아래 프레임을 클릭하십시오.마우스를 위로 이동
hydrate
위 의 함수 콜 ( line)patch
. 원본에 대한 하이퍼링크hydrate
열릴 것이다. - 에서
hydrate
에서 약 후, 줄수, 시에로 15줄 이동 설정에 한다.false
다음에 반환되다assertNodeMatch
돌아온false
중단점을 설정하고 다른 모든 중단점을 제거하십시오. - 같은 경고가 다시 일어나도록 하라.이제 중단점을 맞으면 사형집행이 중단돼야 한다.
hydrate
기능을 발휘하다DevTools 콘솔로 전환하여 평가elm
그 다음에vnode
, nodevnodeg가 DOM인 데 비해, elm은 가상 DOM node.vnodeg가 DOM인 데 동인상 elmgo elmau dom이다.Elm은 HTML로 인쇄되어 있어 어디에서 오류가 발생했는지 알 수 있다.
이 이유는 내 것이기 이다. 왜냐하면 배열 목록을 가져오기 때문이다.AsyncData
렌더링된<tr>
에 의해 꼬리표를 붙이다.v-for
, 내가 놓았다.v-for
암호를 입력하다<client-only>
해결 해결문
이 오류는 디버깅하기에 정말 고통스러울 수 있다.문제를 일으키는 요소를 빨리 가져오려면 다음과 같이 하십시오.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)
// ...
고장난 노드를 콘솔에 넣게 될 것이다.
나는 nuxt 버전과 같은 이슈를 가지고 있었다.2.14.0
vue-package 패키지를 구현하는 동안.그 해결책은 로 그 태그들을 둘러싸는 것이었다.no-ssr
그리고 그것은 문제를 해결했다.
편집:
업데이트된 솔루션 변형(Nuxt 버전이 위에 있는 경우)2.9.0
)
<client-only>
<vue-particles>
</vue-particles>
</client-only>
기존 솔루션:
<no-ssr>
<vue-particles>
</vue-particles>
</no-ssr>
이 문제를 해결할 수 있는 방법은 여러 가지가 있지만, 대부분은 실제적인 해결책이 아니라, 그저 진부한 반창고일 뿐이다.몇 가지 참고 사항:
- 포장하다
<client-only>
태그, 몇 가지 중요한 세부사항을 주의하라. - a를 사용하여
v-show
v-if
- 라이프사이클을 해킹하려고 하는 중
- 기타...
나는 알렉산더 리히터가 쓴 이 멋진 기사를 읽기를 강력히 추천한다.
왜 이런 일이 일어나는지 진단하고 실제 문제를 고쳐야 한다고 그가 설명해 줄 것이다.
기본적으로 어떤 것이 서버에 생성된 것과 다르며 클라이언트에서 하이드레이팅을 했을 때 사용 가능한 것이 매번 이 오류를 발생시킬 것이다.
그 중 일부는 다음과 같다.
- 유효하지 않은 HTML(블록 요소를 내부에 포함)
<p>
,도 마찬가지다.a
다른 태그에 중첩된 태그 등) - 구성 요소를 건드리는 타사 스크립트
- 서버와 클라이언트의 다른 상태
- 임의의 랜덤은 위험하다 (
new Date()
예를 들어) - 인증과 관련된 페이지
나는 알렉산드르 자신의 말로 이런 종류의 문제를 어떻게 다룰 것인가를 이해하기 위해 그 기사를 읽기를 강력히 추천한다.만약 여러분이 급하다면, 여러분은 항상 한 가지 반창고를 사용할 수 있지만, 최상의 성능을 위해 그리고 코드를 깨끗하게 유지하기 위해 실제로 문제를 고치려고 노력한다.
2.10 이상의 Nuxt 버전에서는 설치할 필요가 없으며 기본 구성 요소만 사용하십시오.<client-only>
https://nuxtjs.org/api/components-client-only/에서 언급한 바와 같이.
이전 경고를 확인하십시오.
인"nuxt": "^2.12.2"
, 이전의 경고로부터 쉽게 원인을 찾아낼 수 있다.
제 경우:
틀렸다
<nuxt-link to="/game42day">
<a>Game For Today</a>
</nuxt-link>
정답:
<nuxt-link to="/game42day">
Game For Today
</nuxt-link>
알고 보니, 내 경우에는 HTML 주석 태그가 있었는데, 그것은 이 어리석고 짜증나는 오류를 야기하고 있었다.알아내는데 너무 오래 걸렸지만 누군가에게 도움이 될까봐.
구성 요소를 조건부로 렌더링하는 경우v-if
, 그러면 문제를 해결할 수 있는 두 가지 옵션이 있다.
첫 번째는 원소를 감싸는 것이다.<no-ssr></no-ssr>
꼬리표를 달다
두 번째 접근방식은 교체하는 것이다.v-if
와 함께v-show
, 여기에 Vue 문서로 연결되는 링크가 있다.
내 경우에는 이것을 바꿔야 했다.
<v-expansion-panel-header v-text="name" />
이를 위해:
<v-expansion-panel-header>{{ name }}</v-expansion-panel-header>
그래, 이건 바보같이 들릴거야.서버를 재시작하고 .nnxt 디렉토리를 삭제하는 등 약 15분 동안 여러 가지 솔루션을 시도해 보았지만 너무 게을러 @budden73의 큰 뇌 솔루션을 사용할 수 없었다.결국 나한테 효과가 있었던 건 내 컴퓨터를 다시 시작하는 거였어. 한번 시도해봐.
내가 지금까지 관찰에서 발견한 것은 jQuery(특히)와 같은 제3자 패키지를 사용할 때, 그것들은 때때로 돔에 html 태그를 주입한다는 것이다.그래서 Vue/Nuxt는 돔 트리를 추적하지 않고 불평하기 시작한다.
나도 같은 문제를 겪고 있었는데 얼마 후 모든 jQuery를 제거하고 jQuery 기능을 Vuejs로 교체했는데 그 오류는 모두 사라졌다.
DOM을 수정하는 통합(예: Google Analytics 또는 FB Pixel)을 처리하는 방법에 대한 예는 여기를 참조하십시오.기본적으로 플러그인을 생성하고 SSR에서 제외하십시오.
다음을 참조하십시오.
extend (config, ctx) {
config.resolve.symlinks = false
}
다음 [Vue 경고]를 참조하십시오. 클라이언트측 렌더링된 가상 DOM 트리가 서버에서 렌더링된 콘텐츠(Nuxt / Vue / lerna monorepo )와 일치하지 않음
나 또한 이 문제로 인해 많은 실수를 한다.내가 자주 마주치는 두 가지 경우를 나열해보면 희망이 널 도울 수 있어.
- vuetify 버튼을 사용하여 공통 구성 요소를 생성할 때 다음을 사용하십시오.
<v-btn>{{text}}</v-btn>
예:
<template>
<v-btn
:width="width"
:color="color"
:class="[rounded ? 'rounded-pill' : 'rounded-lg',textColor]"
v-on:click="onClick"
elevation="0"
:outlined="outlined"
:type="type"
:name="name"
:form="form"
:disabled="disabled"
v-bind="$attrs"
>{{ text }}</v-btn>
</template>
- 다음에서 v-html 사용 안 함
<p>
하지 않음: 태그그제. 사용하지 않음:<p v-html='html'></p>
. 사용:<div v-html='html'></div>
.
게다가, 만약 당신이<client-only></client-only>
, 이 문제는 확실히 해결되었지만, 만약 당신이 SEO 페이지나 구글 광고를 보여줘야 한다면, 그것은 좋은 해결책이 아니다.
인라인 요소 내부에 블록 레벨 요소를 사용한 적이 있는지 확인하십시오.
예: 내부, 내부
HTML 테이블을 사용한 경우 태그를 사용했는지 확인하십시오.
내 경우에는, 나는 내 코드를 바꾸었다.
<p v-html="$md.render(post.content)"></p>
로
<p>{{ $md.render(post.content) }}</p>
'IT이야기' 카테고리의 다른 글
라우터 변경 url 응답은 하지만 보기 없음 (0) | 2022.03.14 |
---|---|
vue의 형식 지정 - 속성 'validate'가 'Vue | 요소 | 부[] | 요소[]'에 존재하지 않음 (0) | 2022.03.14 |
XState가 유휴 상태로 유지되지 않음 (0) | 2022.03.14 |
TypeScript에서 비동기/와이트 구문은 어떻게 작동하나? (0) | 2022.03.14 |
이미지 주소를 어레이에 배치하고 소스 VUE JS에서 해당 어레이 인덱스를 사용하는 방법 (0) | 2022.03.14 |