[英]How to render contents based on the params received from vue-router?
我正在使用Vue 3.6.3來構建電影列表頁面。 主頁顯示電影列表,僅包括每部電影的簡要信息,用戶可以點擊每部電影標題的標題進入一個頁面,其中有關於電影的詳細信息。 我使用vue-router來幫助我完成轉換。
根組件是App.vue,實際上它只顯示其子組件。
App.vue中的重要代碼:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
路由器安裝在App.vue上,我創建了一個router.js文件來定義路由,然后在main.js中創建一個路由器。
來自routers.js的代碼:
import App from './App.vue'
import FilmList from './components/FilmList.vue'
import DetailPage from './components/DetailPage.vue'
const routers = [{
path: '/',
redirect: '/filmlist',
component: App,
children: [{
path: '/filmlist',
name: 'filmlist',
component: FilmList
},
{
path: '/detail/:id',
name: 'detail',
component: DetailPage
}
]
}]
export default routers
來自main.js的代碼:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import routes from './routers'
Vue.use(VueRouter)
Vue.config.productionTip = false
const router = new VueRouter({
mode: 'history',
routes: routes
})
new Vue({
router: router,
render: h => h(App),
}).$mount('#app')
App.vue組件有兩個子節點,FilmList和DetailPage。 首先,將顯示FilmList,在用戶單擊其中一個之后,它將根據路由器中的id參數跳轉到某個電影的詳細頁面。 在收到id參數后,DetailPage.vue應該從電影列表中選擇一部電影並顯示其詳細內容。
來自FilmList.vue的代碼:
<template>
<div id="filmlist">
<film-brief
v-for="(film, index) in filmList[pageIndex-1]"
v-bind:key="film._id"
v-bind:index="index + groupCount*(pageIndex-1)"
v-bind:film="film"
></film-brief>
<div class="buttons">
<jump-button
class="button"
v-for="index in buttonIndexList"
:key="index.id"
v-bind:index="index"
v-on:jump-page="pageIndex = index.id"
></jump-button>
</div>
</div>
</template>
<script>
import FilmBrief from "../components/FilmBrief.vue";
import films from "../assets/films.json";
import JumpButton from "../components/JumpButton.vue";
const GroupCount = 10;
export default {
name: "FilmList",
data: function() {
return {
films,
pageIndex: 1,
pageCount: Math.ceil(films.length / GroupCount),
groupCount: GroupCount
};
},
components: {
FilmBrief,
JumpButton
},
......
FilmBrief.vue的代碼:
<template>
<div class="film-brief">
<div class="poster">
<img :src="imgSrc">
</div>
<div class="info">
<router-link
:to="{
name: 'detail',
params: {
id: index
}
}"
>
<div class="heading" v-html="title"></div>
</router-link>
<div class="ratings">{{film.rating.average}}</div>
<div class="ontime">{{pubdate}}</div>
<div class="type">{{genres}}</div>
</div>
</div>
</template>
<script>
import errorImg from "../assets/imgErr.jpg";
export default {
name: "FilmBrief",
props: ["film", "index"],
data: function() {
return {
imgSrc: "",
imgErrSrc: errorImg
};
},
methods: {
loadImg(resolve, reject) {
let originImgSrc = this.film.poster;
let img = new Image();
img.src = originImgSrc;
img.onload = function() {
resolve({
src: img.src
});
};
img.onerror = function(e) {
reject(e);
};
}
},
created: function() {
this.loadImg(
response => {
this.imgSrc = response.src;
},
reject => {
console.log("圖片加載失敗");
this.imgSrc = this.imgErrSrc;
}
);
},
......
來自DetailPage.vue的代碼:
<template>
<div class="detail-page">
<div class="poster">
<img :src="this.imgSrc">
</div>
<div class="details">
<ul>
<li id="title" v-html="title"></li>
<li id="director">{{directors}}</li>
<li id="writers">{{writers}}</li>
<li id="casts">{{casts}}</li>
<li id="genres">{{genres}}</li>
<li id="duration">{{duration}}</li>
<li id="pubdate">{{pubdate}}</li>
<li id="summary"></li>
</ul>
</div>
</div>
</template>
<script>
import errorImg from "../assets/imgErr.jpg";
import films from "../assets/films.json";
export default {
name: "DetailPage",
props: [],
data: function() {
return {
id_: this.$route.params.id,
film: films[id_],
imgSrc: "",
imgErrSrc: errorImg,
duration: "片長:" + this.film.duration + "分鍾",
summary: "簡介:" + this.film.summary
};
},
methods: {
loadImg(resolve, reject) {
let originImgSrc = this.film.poster;
let img = new Image();
img.src = originImgSrc;
img.onload = function() {
resolve({
src: img.src
});
};
img.onerror = function(e) {
reject(e);
};
},
getList(name, list) {
let result = "";
result += name;
for (let i = 0; i < list.length; i++) {
result += list[i].name;
if (i !== list.length - 1) {
result += " / ";
}
}
return result;
}
},
created: function() {
this.loadImg(
response => {
this.imgSrc = response.src;
},
reject => {
console.log("圖片加載失敗");
this.imgSrc = this.imgErrSrc;
}
);
},
computed: {
title: function() {
let originalTitle = "";
originalTitle += this.film.title;
let index = originalTitle.indexOf(" ");
let input = originalTitle[index - 1];
let isPunc =
(input >= "A" && input <= "Z") || (input >= "a" && input <= "z");
if (!isPunc) {
return (
originalTitle.slice(0, index) +
"<br>" +
originalTitle.slice(index + 1)
);
} else {
return originalTitle;
}
},
directors: function() {
return this.getList("導演:", this.film.directors);
},
writers: function() {
return this.getList("編劇:", this.film.writers);
},
casts: function() {
return this.getList("主演:", this.film.casts);
},
genres: function() {
let genres = this.film.genres;
let str = "";
for (let i = 0; i < genres.length; i++) {
str += genres[i];
if (i !== genres.length - 1) {
str += " / ";
}
}
return str;
},
pubdate: function() {
let dates = this.film.pubdate;
if (dates[0] === "") {
return "上映時間未知";
} else {
return "上映時間:" + dates[0];
}
}
}
};
</script>
單擊后,瀏覽器中顯示的路徑就可以了,如“ http:// localhost:8080 / detail / 11 ”,但是,頁面沒有顯示任何內容,控制台中的錯誤類似於:
[Vue warn]: Error in data(): "ReferenceError: id_ is not defined"
found in
---> <DetailPage> at src/components/DetailPage.vue
<App> at src/App.vue... (1 recursive calls)
ReferenceError: id_ is not defined
at VueComponent.data (DetailPage.vue?b507:31)
at getData (vue.runtime.esm.js?2b0e:4742)
at initData (vue.runtime.esm.js?2b0e:4699)
at initState (vue.runtime.esm.js?2b0e:4636)
at VueComponent.Vue._init (vue.runtime.esm.js?2b0e:5000)
at new VueComponent (vue.runtime.esm.js?2b0e:5148)
at createComponentInstanceForVnode (vue.runtime.esm.js?2b0e:3283)
at init (vue.runtime.esm.js?2b0e:3114)
at merged (vue.runtime.esm.js?2b0e:3301)
at createComponent (vue.runtime.esm.js?2b0e:5972)
[Vue warn]: Error in created hook: "TypeError: Cannot read property 'poster' of undefined"
found in
---> <DetailPage> at src/components/DetailPage.vue
<App> at src/App.vue... (1 recursive calls)
<Root>
以及其他許多警告。
后來我假設也許是因為id param應該在其他屬性訪問它之前加載,所以我將它添加到DetailPage.vue中創建的像:
`created: function() {
this.film = films[this.$route.params.id];
this.loadImg(
response => {
this.imgSrc = response.src;
},
reject => {
console.log("圖片加載失敗");
this.imgSrc = this.imgErrSrc;
}
);
},
現在可以加載一些信息,但其他一些信息不能,如海報和持續時間。 警告包括:
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in data(): "TypeError: Cannot read property 'duration' of undefined"
found in
---> <DetailPage> at src/components/DetailPage.vue
<App> at src/App.vue... (1 recursive calls)
<Root>
TypeError: Cannot read property 'duration' of undefined
at VueComponent.data (DetailPage.vue?b507:34)
at getData (vue.runtime.esm.js?2b0e:4742)
at initData (vue.runtime.esm.js?2b0e:4699)
at initState (vue.runtime.esm.js?2b0e:4636)
at VueComponent.Vue._init (vue.runtime.esm.js?2b0e:5000)
at new VueComponent (vue.runtime.esm.js?2b0e:5148)
at createComponentInstanceForVnode (vue.runtime.esm.js?2b0e:3283)
at init (vue.runtime.esm.js?2b0e:3114)
at merged (vue.runtime.esm.js?2b0e:3301)
at createComponent (vue.runtime.esm.js?2b0e:5972)
那么,為什么會這樣,我怎樣才能顯示所有信息?
如果我的英語不好讓你煩惱,請道歉,並提前致謝!
您的問題是由您的DetailPage
組件中的data()
函數引起的。
data: function() {
return {
id_: this.$route.params.id,
film: films[id_],
imgSrc: "",
imgErrSrc: errorImg,
duration: "片長:" + this.film.duration + "分鍾",
summary: "簡介:" + this.film.summary
};
},
有幾個問題:
film: films[id_]
不起作用 - id_
未在任何地方定義,因此film
道具也將不確定。
duration: "片長:" + this.film.duration + "分鍾"
- 您無法使用this
訪問其他data
道具。
您應該使您的data()
函數包含默認/空/占位符數據:
data: function() {
return {
id_: this.$route.params.id, // this is fine - you can access $route because it's global
film: {}, // empty object or some object type containing placeholder props
imgSrc: "",
imgErrSrc: errorImg,
duration: "",
summary: ""
};
},
然后在您created
或mounted
鈎子中加載它:
created: function() {
this.film = films[this.$route.params.id];
this.duration = "片長:" + this.film.duration + "分鍾";
this.summary = "簡介:" + this.film.summary;
this.loadImg(
response => {
this.imgSrc = response.src;
},
reject => {
console.log("圖片加載失敗");
this.imgSrc = this.imgErrSrc;
}
);
},
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.