首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据从vue-路由器接收到的params来呈现内容?

如何根据从vue-路由器接收到的params来呈现内容?
EN

Stack Overflow用户
提问于 2019-04-26 13:37:54
回答 1查看 898关注 0票数 0

我正在使用Vue 3.6.3建立一个电影列表页面。主页显示电影列表,仅包括每部影片的简短信息,用户可以单击每部影片的标题以输入有关于该影片的详细信息的页面。我用vue-路由器来帮助我完成过渡。

根组件是App.vue,实际上它只会显示它的子组件。

App.vue中的重要代码:

代码语言:javascript
复制
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

路由器被挂载在App.vue上,我创建了一个routers.js文件来定义路由,然后在main.js中创建一个路由器。

Routers.js的代码:

代码语言:javascript
复制
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的代码:

代码语言:javascript
复制
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 param的某个电影的详细页面。在接收到id param后,DetailPage.vue应该从电影列表中选择一部电影并显示其详细内容。

来自FilmList.vue的代码:

代码语言:javascript
复制
<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的代码:

代码语言:javascript
复制
<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的代码:

代码语言:javascript
复制
<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“一样没有问题,但是页面没有显示任何内容,控制台中的错误类似于:

代码语言:javascript
复制
[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)
代码语言:javascript
复制
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)
代码语言:javascript
复制
[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中的中,如下所示:

代码语言:javascript
复制
`created: function() {
    this.film = films[this.$route.params.id];
    this.loadImg(
      response => {
        this.imgSrc = response.src;
      },
      reject => {
        console.log("图片加载失败");
        this.imgSrc = this.imgErrSrc;
      }
    );
  },

现在可以加载一些信息,但另一些信息不能加载,比如海报和持续时间。警告包括:

代码语言:javascript
复制
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>
代码语言:javascript
复制
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)

那么,为什么是这样,我怎样才能显示所有的信息呢?

如果我的英语不好打扰到你,请道歉,并提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-04-26 14:05:35

您的问题是由您在data()组件中的DetailPage函数引起的。

代码语言:javascript
复制
  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()函数包含默认/空/占位符数据:

代码语言:javascript
复制
  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: ""
    };
  },

然后在createdmounted钩子中加载它:

代码语言:javascript
复制
  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;
      }
    );
  },
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55868869

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档