#vue.js #vue-component #vue-router #vuejs3
Вопрос:
Я изучаю VueJS, создавая практическое приложение, и я застрял в точке, где внутри Authors
компонента у меня есть список авторов. Я хочу иметь возможность нажать на элемент списка и перейти к AuthorDetail
компоненту, пока все в порядке. Проблема возникает, когда я использую панель навигации вверху для перехода к другому виду, например Home
, или About
компонент AuthorDetail остается видимым (он должен исчезнуть!).
Код внутри App.vue
<template>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/authors">Authors</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view />
</template>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
max-width: 480px;
margin: auto;
border: 1px solid #2c3e50;
border-radius: 5px;
padding: 20px;
}
#nav {
padding: 10px;
border-bottom: 1px solid #e2e2e2;
margin-bottom: 30px;
a {
font-weight: bold;
color: #2c3e50;
amp;.router-link-exact-active {
color: #42b983;
}
}
}
</style>
Код в router/index.js
import { createRouter, createWebHistory } from "vue-router";
import Home from "../views/Home.vue";
import Authors from "../views/Authors.vue";
import AuthorDetail from "../views/AuthorDetail.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/authors",
name: 'Authors',
component: Authors
},
{
path: "/authors/:id",
name: "AuthorDetail",
component: AuthorDetail
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});
export default router;
Код внутри Authors
компонента.
<template>
<div>
<h1>Authors</h1>
<p>Most Popular Authors (TheTestRequest API)</p>
<div class="authors-list" :key="author.id" v-for="author in authors">
<router-link :to="{ name: 'AuthorDetail', params: { id: author.id}}">
<AuthorCard @click="showAuthor(author.id)" :author="author"></AuthorCard>
</router-link>
</div>
</div>
</template>
<script>
import AuthorCard from '@/components/AuthorCard'
export default {
name: "Authors",
components: {
AuthorCard
},
data(){
return {
authors: []
}
},
methods: {
async fetchAuthors(){
const res = await fetch('https://thetestrequest.com/authors')
const data = await res.json()
return data
},
showAuthor(authorId){
console.log("Author Clicked", authorId);
}
},
async created() {
this.authors = await this.fetchAuthors()
},
}
</script>
<style lang="scss" scoped>
.authors-list {
margin-top: 2em;
// transition: box-shadow .3s;
a {
text-decoration: none;
color: black;
}
}
</style>
Примечание: Я использую thetestrequest.com чтобы получить данные для этого практического приложения.
Образцы пользовательского интерфейса:
Ответ №1:
Оказывается, в консоли была ошибка, которая помогла мне решить проблему.
Ошибка:
AuthorDetail.vue?0959:6 Uncaught (in promise) TypeError: Cannot read property 'avatar' of null
at Proxy.eval (AuthorDetail.vue?0959:6)
at renderComponentRoot (runtime-core.esm-bundler.js?5c40:1168)
at componentEffect (runtime-core.esm-bundler.js?5c40:5214)
at reactiveEffect (reactivity.esm-bundler.js?a1e9:42)
at effect (reactivity.esm-bundler.js?a1e9:17)
at setupRenderEffect (runtime-core.esm-bundler.js?5c40:5167)
at mountComponent (runtime-core.esm-bundler.js?5c40:5126)
at processComponent (runtime-core.esm-bundler.js?5c40:5084)
at patch (runtime-core.esm-bundler.js?5c40:4690)
at componentEffect (runtime-core.esm-bundler.js?5c40:5287)
Поэтому простой v-if="avatar"
AuthorDetail
шаблон проверки внутри сделал для меня трюк.