Ошибка Nuxt.js: визуализированное виртуальное дерево DOM на стороне клиента не соответствует отображаемому на сервере содержимому - PullRequest
0 голосов
/ 05 октября 2019

Как я могу исправить эту ошибку в Nuxt? Совет был бы оценен, я пытался заставить это работать в течение нескольких часов.


[Vue warn]: 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. (repeated 9 times)
value @ vendors.app.js:12923
value @ vendors.app.js:12923
value @ vendors.app.js:12923
(anonymous) @ vendors.app.js:12923
(anonymous) @ commons.app.js:20499
setTimeout (async)
(anonymous) @ commons.app.js:20482
./node_modules/vue/dist/vue.runtime.esm.js @ commons.app.js:20512
__webpack_require__ @ runtime.js:791
fn @ runtime.js:151
(anonymous) @ app.js:2069
./.nuxt/client.js @ app.js:3157
__webpack_require__ @ runtime.js:791
fn @ runtime.js:151
0 @ app.js:19627
__webpack_require__ @ runtime.js:791
checkDeferredModules @ runtime.js:46
webpackJsonpCallback @ runtime.js:33
(anonymous) @ app.js:1
vendors.app.js:12923 info You are running Vue in development mode.

Это происходит, когда я вызываю это из AsyncData ():

      context.store.dispatch('retrievePosts', {'feedUrl': '/' + process.env.backendPublicApiPrefix + '/posts', 'selection': 'feed'} );

В моем магазине Vuex:

export const actions = {

  async retrievePosts(context, { feedUrl, selection }) {
    context.commit("setLoading");
    context.commit("incrementPage");
    try {

      // only make an ajax call if we are not on or past the last page of posts
      if (!context.state.lastPage || (context.state.lastPage && (context.state.page <= context.state.lastPage))) {

        let finalUrl = feedUrl + '?page=' + context.state.page;

        finalUrl += '&viewBy=' + 'feed';
        const { data, status } = await this.$axios.get(finalUrl);
        if (!data) {
          throw ({ statusCode: 404, message: 'Something went wrong while retrieving the post feed. The link you clicked on may be broken or no longer exist.' });
        } else {
          if (data.last_page) {
            context.commit("setLastPage", data.last_page);
          }
          if (data.data && (data.data.length > 0)) {
            context.commit("appendPosts", data.data);
          } else {
            if (state.page < 1) {
              // context.state.error = "response.data.Error";
            }
          }
        }
      }

    } catch (e) {
      throw ({ statusCode: 404, message: 'Something went wrong while retrieving the post feed. The link you clicked on may be broken or no longer exist.' });
    }
    context.commit("unsetLoading");
  },
};


export const mutations = {
  setLoading(state) {
    state.loading = true;
  },
  unsetLoading(state) {
    state.loading = false;
  },
  setLastPage(state, pageId) {
    state.lastPage = pageId;
  },
  resetPostFeed(state) {
    console.log('resetPostFeed');
    state.posts = [];
    state.page = 0;
    state.lastPage = null;
  },
  setPostFeed(state, { postFeedSettings, posts }) {
    state.posts = posts;
  },
  setPage(state, pageId) {
    state.page = pageId;
  },
  incrementPage(state) {
    state.page++;
  },
  appendPosts(state, newPosts) {
    state.posts = state.posts.concat(newPosts);
  },
};

В моем шаблоне:

        <div v-for="post in postsFromStore">
          <news-feed-content-card
            :postObj="post"
            :authorObj="post.user"
          />
        </div>

Обратите внимание, что все работает нормально, если я не вызываю это из asyncData (), но мне нужно сделать этодля SSR:

context.store.dispatch('retrievePosts', {'feedUrl': '/' + process.env.backendPublicApiPrefix + '/posts', 'selection': 'feed'} );

Как я могу решить эту проблему? Я чувствую, что что-то здесь мне не хватает, но я не могу понять, что именно.

РЕДАКТИРОВАТЬ: тег no-ssr устарел и заменяется на Using которая просто скрывает ошибку, не совсем исправляет ее.

Я сузил это до:

                <!-- this causes an error: The client-side rendered virtual DOM tree is not matching server-rendered content. -->
                <client-only>
                  <p class="tw-text-xs tw-pt-1 tw-text-gray-600" v-html="authorObj.bioHeadline"></p>
                </client-only>

authorObj.bioHeadline имеет HTML как: Founder at <a href='https://www.example.com' target='_blank'>Domain</a>

, и я хочу включить его в режиме SSR (удалитьтолько для клиента), но это приводит к этой ошибке:

[Vue warn]: 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. (repeated 9 times)

1 Ответ

1 голос
/ 06 октября 2019

Разобрался.

authorObj.bioHeadline имеет ссылку, и из-за кода ниже у меня была вложенная ссылка .... которая, я думаю, не разрешена.

              <nuxt-link :to="getAuthorUrl">
                <p class="tw-font-bold kb-subtle-link tw-text-sm md:tw-text-lg">{{ authorObj.fullName }}</p>
                  <p class="tw-text-xs tw-pt-1 tw-text-gray-600" v-html="authorObj.bioHeadline"></p>
              </nuxt-link>

Сгенерированный HTML:

<a href="/" class=""><p class="tw-font-bold kb-subtle-link tw-text-sm md:tw-text-lg">kp</p> <p class="tw-text-xs tw-pt-1 tw-text-gray-600">Founder at <a href="https://www.example.com" target="_blank">Domain</a></p></a>
...