16. Vue project-page details page uses Ajax to obtain dynamic data (mainly solves three problems that arise)

I added the data in the details page before, but now I need to use ajax to get the dynamic data

Detail.vue parent component requests axios

Axios must be introduced first here

Because the details page comes in from the homepage entry point, the routing will be different. The passed parameters go to the browser to switch to Vue mode browsing, as shown in the following figure, when requesting the interface, you need to carry the parameter id, and the parameter method should be this. $route.params.id
Insert picture description here
Detail.vue

<template>
  <div class="detail">
    <detail-banner
      :sightName="sightName"
      :bannerImg="bannerImg"
      :gallaryImgs="gallaryImgs"
    ></detail-banner>
    <detail-header></detail-header>
    <div class="content">
      <detail-list :list="list"></detail-list>
    </div>
  </div>
</template>

<script>
import DetailBanner from './components/Banner'
import DetailHeader from './components/Header'
import DetailList from './components/List'
import axios from 'axios'
export default {
     
     
  name: 'Detail',
  components: {
     
     
    DetailBanner,
    DetailHeader,
    DetailList
  },
  data() {
     
     
    return {
     
     
      sightName: '',
      bannerImg: '',
      gallaryImgs: [],
      list: []
    }
  },
  methods: {
     
     
    getDetailInfo() {
     
     
      axios({
     
     
        url: '/static/mock/detail.json',
        method: 'get',
        params: {
     
     
          id: this.$route.params.id
        }
      }).then(res => {
     
     
        console.log(res)
        if (res.data.ret && res.data.data) {
     
     
          this.sightName = res.data.data.sightName
          this.bannerImg = res.data.data.bannerImg
          this.gallaryImgs = res.data.data.gallaryImgs
          this.list = res.data.data.categoryList
        }
      })
    }
  },
  mounted() {
     
     
    this.getDetailInfo()
  }
}
</script>

<style lang="scss" scoped>
.content {
     
     
  height: 20rem;
}
</style>


Sub-components modify data according to the data returned by the interface

Banner.vue

Child component props receive data from the parent component
Insert picture description here

<template>
  <div>
    <div class="banner" @click="handleBannerClick">
      <img class="banner-img" :src="bannerImg" />
      <div class="banner-info">
        <div class="banner-title">{
   
   { this.sightName }}</div>
        <div class="banner-number">
          <span class="iconfont banner-icon">&#xe62d;</span>
          {
   
   {this.gallaryImgs.length}}
        </div>
      </div>
    </div>
    <common-gallary
      :imgs="gallaryImgs"
      v-show="showGallay"
      @close="handleGallaryClose"
    ></common-gallary>
  </div>
</template>

<script>
import CommonGallary from 'common/gallary/Gallary'
export default {
     
     
  name: 'DetailBanner',
  props: {
     
     
    sightName: String,
    bannerImg: String,
    gallaryImgs: Array
  },
  data() {
     
     
    return {
     
     
      showGallay: false
    }
  },
  methods: {
     
     
    handleBannerClick() {
     
     
      this.showGallay = true
    },
    handleGallaryClose() {
     
     
      this.showGallay = false
    }
  },
  components: {
     
     
    CommonGallary
  }
}
</script>

<style lang="scss" scoped>
.banner {
     
     
  overflow: hidden;
  height: 0;
  padding-bottom: 50%;
  position: relative;
  .banner-img {
     
     
    width: 100%;
  }
  .banner-info {
     
     
    display: flex;
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    line-height: 0.6rem;
    color: #fff;
    background-image: linear-gradient(
      top,
      rgba(0, 0, 0, 0),
      rgba(0, 0, 0, 0.8)
    );
    .banner-title {
     
     
      flex: 1;
      font-size: 0.32rem;
      padding: 0 0.2rem;
    }
    .banner-number {
     
     
      height: 0.4rem;
      line-height: 0.4rem;
      margin-top: 0.1rem;
      padding: 0 0.32rem;
      border-radius: 0.2rem;
      background: rgba(0, 0, 0, 0.6);
      font-size: 0.24rem;
      .banner-icon {
     
     
        margin-right: 0.1rem;
      }
    }
  }
}
</style>

Now the data replacement of this page is basically completed, but there are still some minor problems, resulting in a bad experience

Question one

When we clicked in from the homepage for the first time, the id was 0001. When we returned to the homepage and changed the entry, the id was still 0001, and there was no re-fetching data
Insert picture description here
solution:

Because the detail page is cached through keep-alive, the mounted() hook function will only be executed once. If you want to remove the cache of the 在keep-alive标签加上exclude=“Detail”detail page now, the mounted() hook function will be executed every time you enter the detail page

Insert picture description here
Insert picture description here

Question two

Sliding multiple pages will affect each other; sliding the homepage, the detail page will also follow, for example:

Insert picture description hereSolution:

The vue.js official document provides us with a method of scrolling behavior, just add something under the routes in the route.
Attach the official link: https://router.vuejs.org/zh/guide/advanced/scroll-behavior .html#%E5%BC%82%E6%AD%A5%E6%BB%9A%E5%8A%A8

Insert picture description here

Question three

Insert picture description here
Vue uses keep-alive to cache components. The exclude attribute indicates that the cached component is to be removed, and other components will be cached.

When this property is used, the activated() deactivated() method of the corresponding component will not be executed.

Insert picture description here
Solution:

change into

  mounted() {
    
    
    window.addEventListener('scroll', this.handleScroll)
  },
  destroyed() {
    
    
    window.removeEventListener('scroll', this.handleScroll)
  }

Guess you like

Origin blog.csdn.net/weixin_45811256/article/details/109491171