Как отобразить элемент vue, когда я нажимаю на vue список всех элементов? - PullRequest
0 голосов
/ 12 апреля 2020

Я новичок в vueJS / Nuxt, и я создаю блог, используя WordPress в качестве безголовой CMS. Wordpress предоставляет данные из остальных API, и в vuejs я использую эти данные и отображаю их на странице. У меня есть такая структура проекта: enter image description here

Я сталкиваюсь с проблемой при переходе от портретов / индекса. vue к портретам / _slug. vue. - портреты / индекс. vue отображать все мои собственные портреты типа пост. Вот код:

   <template>
      <div>
        <app-masthead></app-masthead>
        <div class="portraits">
          <main>
            <div class="portrait" v-for="portrait in sortedPortraits" :key="portrait.id">
              <h3>
                <a :href="`portraits/${portrait.slug}`">{{ portrait.title.rendered }}</a>
              </h3>
              <small>{{ portrait.date | dateformat }}</small>
              <div v-html="portrait.excerpt.rendered"></div>
              <a :href="`portraits/${portrait.slug}`" class="readmore slide">Read more ⟶</a>
            </div>
          </main>
          <aside>
            <h2 class="tags-title">Tags</h2>
            <div class="tags-list">
              <ul>
                <li
                  @click="updateTag(tag)"
                  v-for="tag in tags"
                  :key="tag.id"
                  :class="[tag.id === selectedTag ? activeClass : '']"
                >
                  <a>{{ tag.name }}</a>
                  <span v-if="tag.id === selectedTag">✕</span>
                </li>
              </ul>
            </div>
          </aside>
        </div>
      </div>
    </template>

    <script>
    import AppMasthead from "@/components/AppMasthead.vue";

    export default {
      components: {
        AppMasthead
      },
      data() {
        return {
          selectedTag: null,
          activeClass: "active"
        };
      },
      computed: {
        portraits() {
          return this.$store.state.portraits;
        },
        tags() {
          return this.$store.state.tags;
        },
        sortedPortraits() {
          if (!this.selectedTag) return this.portraits;
          return this.portraits.filter(el => el.tags.includes(this.selectedTag));
        }
      },
      created() {
        this.$store.dispatch("getPortraits");
      },
      methods: {
        updateTag(tag) {
          if (!this.selectedTag) {
            this.selectedTag = tag.id;
          } else {
            this.selectedTag = null;
          }
        }
      }
    };
    </script>

    <style lang="scss">


    </style>

- portraits/_slug.vue display one item portrait. Here is the code : 
<template>
  <main class="portrait individual">
    <h1>{{ portrait.title.rendered }}</h1>
    <small class="date">{{ portrait.date | dateformat }}</small>
    <section v-html="portrait.content.rendered"></section>
  </main>
</template>

<script>
export default {
  computed: {
    portraits() {
      return this.$store.state.portraits;
    },
    portrait() {
      debugger
      return this.portraits.find(el => el.slug === this.slug);
    }
  },
  data() {
    return {
      slug: this.$route.params.slug
    };
  },
  created() {
    this.$store.dispatch("getPortraits");
  }
};
</script>

<style lang="scss" scoped>

</style>

Когда я нажимаю на readmore, у меня появляется следующая ошибка:

TypeError
Cannot read property 'title' of undefined

enter image description here

и этот метод не вызывается

portrait() {
      debugger
      return this.portraits.find(el => el.slug === this.slug);
    }

Мой портрет не инициализирован! Что мне не хватает, пожалуйста? Спасибо

1 Ответ

0 голосов
/ 14 апреля 2020

Вы можете написать таким образом.

<template>
  <main class="portrait individual">
    <h1 v-if="portrait">{{ portrait.title.rendered }}</h1>
  </main>
</template>

<script>
export default {
  computed: {
    portraits() {
      return this.$store.state.portraits;
    },
    portrait() {
      return this.portraits.find(el => el.slug === this.slug);
    }
  },
  data() {
    return {
      slug: this.$route.params.slug
    };
  },
  created() {
    this.$store.commit("getPortraits");
  }
};
</script>

Кажется, this.$store.dispatch("getPortraits"); не вызывается.

Вместо этого Вы можете использовать this.$store.commit("getPortraits"); в created().

В хранилище / индекс. js.

export const state = () => ({
  portraits: []
});

export const mutations = {
  getPortraits(state) {
    state.portraits.push({
      slug: "a",
      title: {
        rendered: "hello"
      }
    });
  }
};

Я пробовал в эту песочницу .

По-другому, вы также можете использовать портреты данные в data() объекте.

<template>
  <main class="portrait individual">
    <h1 v-if="portrait">{{ portrait.title.rendered }}</h1>
  </main>
</template>

<script>
export default {
  computed: {
    portrait() {
      return this.portraits.find(el => el.slug === this.slug);
    }
  },
  data() {
    return {
      slug: this.$route.params.slug,
      portraits: this.$store.state.portraits
    };
  },
  created() {
    this.$store.commit("getPortraits");
  }
};
</script>

И используйте v-if="portrait" в теге h1 , поскольку портретный объект может иметь начальное значение, например, неопределенный или пустой массив.

...