去哪儿-19-detail-ajax

目标: 使用ajax获取详情页面的数据

数据形式:

{
  "ret": true,
  "data": {
    "sightName": "迪士尼小镇",
    "bannerImg": "http://img1.qunarzz.com/sight/p0/1707/82/821428e3bbf93bbaa3.water.jpg_600x330_2385695d.jpg",
    "galleryImgs": ["http://img1.qunarzz.com/sight/p0/1707/c2/c2be8d6326cdea1a3.water.jpg_r_800x800_97e80887.jpg", "http://img1.qunarzz.com/sight/p0/1707/c4/c48e92049336b8ffa3.water.jpg_r_800x800_42a54b54.jpg"],
    "categoryList": [{
      "title": "成人票",
      "children": [{
        "title": "成人三人团票",
        "children": [{
          "title": "成人三人团票-亲情套餐"
        }]
      }, {
        "title": "成人五人团票"
      }]
    }, {
      "title": "学生票"
    }, {
      "title": "儿童票"
    }, {
      "title": "特惠票"
    }]
  }
}

在Detail.vue中借助ajax请求: 借用生命周期钩子来实现。

methods: {
    getDetailInfo () {
        axios.get('/api/detail.json')
    }
},
mounted() {
    this.getDetailInfo()
}

使用ajax请求要记得引入axios。此外,我们每次请求不同的详情页的时候,希望将对应的id带给后端,以此来获取不同详情页面的数据。 而这个id是动态路由的一个参数,在路由定义中是这样的:

path: '/detail/:id',
name: 'Detail',
component: Detail

上面的这个动态路由会把对应的id存放在id的这个变量当中,在页面上就可以这样写:axios.get('/api/detail.json?id=' + this.$route.params.id), 但是这样写太麻烦,换一种写法:

axios.get('/api/detail.json', {
        params: {
            id: this.$route.params.id
        }
    })

当ajax数据获取完毕之后就可以then了:

methods: {
    getDetailInfo () {
        axios.get('/api/detail.json', {
            params: {
                id: this.$route.params.id
            }
        }).then(this.handleGetDataSucc)
    },
    handleGetDataSucc (res) {
        var res = res.data
        if (res.ret && res.data) {
            const data = res.data
            this.sightName = data.sightName
            this.bannerImg = data.bannerImg
            this.galleryImgs = data.galleryImgs
            this.list = data.categoryList
        }
    }
}

res就是获取到的数据,然后将这些获得的数据以属性的形式分别传递给子组件。

<div>
    <detail-banner 
        :sightName="sightName"
        :bannerImg="bannerImg"
        :bannerImgs="galleryImgs"
    >detail-banner>
    <detail-header>detail-header>
    <div class="content">
        <detail-list :list="list">detail-list>
    div>
div>

子组件接收数据:
Banner.vue中接收:

props: {
    sightName: String,
    bannerImg: String,
    bannerImgs: Array
}

数据替换:

<div>
    <div class="banner" @click="handleBannerClick">
        <img class="banner-img" :src="bannerImg" alt="">
        <div class="banner-info">
            <div class="banner-title">
                {{ this.sightName }}
            div>
            <div class="banner-number">
                <span class="iconfont banner-icon">span>
                {{ this.bannerImgs.length }}
            div>
        div>
    div>
    <common-gallery 
        :imgs="bannerImgs" 
        v-show="showGallery"
        @close="handleBannerGallery"
    >common-gallery>
div>

完成上面的数据替换,依然能够呈现出想要的效果。

但是,在页面上点击详情页的时候会发现,当我点击第一个详情页的时候它发了id为0001的ajax数据,而请求第二个详情页的时候并没有发送id为0002的ajax数据,原因是Detail页面使用keep-alive做了缓存,所以mounted只会执行一次,跟之前的页面一样,如果想要请求不同页面的时候都发送一个ajax请求的话,就要配合activated的生命周期钩子,但是这里,我们采用一种新的方式: 在我们的根组件App.vue中原本是这样的:

<keep-alive>
    <router-view/>
keep-alive>

表示所有路由的页面都做了一个缓存,如果我不想让详情页面做缓存,就可以这样做:

<keep-alive exclude="Detail">
    <router-view/>
keep-alive>

其中Detail是详情页的名字,表示除了Detail页面都会缓存,只有Detail页面不会被缓存了,那么这个时候在请求不同详情页面的时候mounted钩子都会被执行。

每个组件中的name的作用是什么?
1. 递归组件需要使用
2. 相对某个页面取消缓存的时候需要使用
3. 网页中Vue开发调试工具会显示一个个组件的名字,就是这个name

一个小bug: 点击后面的详情页时会发现跳转过来的页面不是从顶部开始显示的,拖动效果在多个页面之间会互相影响。解决方法:Vue Router官网有一个滚动行为,在我们项目的路由部分添加以下内容:

scrollBehavior (to, from, savedPosition) {
    return {
    x: 0,
    y: 0
    }
}

表示每次做路由切换的时候都让显示的页面从(0,0)出开始显示,页面切换的时候始终从最顶部开始显示。

你可能感兴趣的:(Vue项目实战)