【前端】Vue项目:旅游App-(21)detail:房屋详情页及其数据、返回导航栏、轮播图

本项目博客总结:【前端】Vue项目:旅游App-博客总结

目标

完成detail页面的返回导航栏与轮播图。(detail页面是点进houseList中的页面:)

在这里插入图片描述
对应数据:要传入houseId,根据参数houseId的不同,会返回不同的数据。如:

123.207.32.32:1888/api/detail/infos?houseId=20061007
123.207.32.32:1888/api/detail/infos?houseId=44173741

过程与代码

请求数据:request+store

请求数据:

service/modules/detail.js:

// 此文件保存所有detail页面的网络请求
import HYRequest from '@/service/request'

export function getDetailInfos(houseId) {
    
    
    return HYRequest.get({
    
    
        url: '/detail/infos',
        params: {
    
    
            houseId
        }
    })
}

service/index:

// 此文件导入并导出所有要使用的service

export * from '@/service/modules/city'
export * from '@/service/modules/home'
export * from '@/service/modules/detail'

管理数据:

store/modules/detail:

import {
    
     defineStore } from "pinia";
import {
    
     getDetailInfos } from '@/service/modules/detail'

const useDetailStore = defineStore('detail', {
    
    
    state: () => {
    
    
        return {
    
    
            detailData: {
    
    },

        }
    },
    actions: {
    
    
        async fetchDetailData(houseId) {
    
    
            const res = await getDetailInfos(houseId)
            console.log(res)
            this.detailData=res.data
        }
    }
})

export default useDetailStore

detail.vue:

const route = useRoute()
const houseId = route.params.id
const detailStore = useDetailStore()

detailStore.fetchDetailData(houseId)
const {
    
     detailData } = storeToRefs(detailStore)

页面请求到的数据:

在这里插入图片描述

这个数据较为复杂,我们在做每个组件的时候最好把数据拆分,如:做轮播图的组件就只传跟轮播图相关的数据。

不要想着“一次到位”,这样会很麻烦。

轮播图组件

Swipe 轮播 - Vant 4 (gitee.io)

相关图片数据:我们用url进行轮播。

在这里插入图片描述
根据Vant库做出来的轮播图组件:detail-swipe

<template>
    <div class="swipe">
        <van-swipe class="swipeList" :autoplay="3000" lazy-render>
            <van-swipe-item v-for="item in props.swipeData" :key="item">
                <img :src="item.url" />
            </van-swipe-item>
        </van-swipe>
    </div>
</template>

<script setup>
const props = defineProps({
      
      
    swipeData: {
      
      
        type: Array,
        default: () => []
    }
})
</script>

<style lang="less" scoped>

</style>

detail

<!-- 轮播图 -->
<detailSwipe :swipe-data="detailData.mainPart.topModule.housePicture.housePics"/>

bug:undefined

出现了这样的bug:

在这里插入图片描述
相关分析与解决方法:【前端debug】轮播图报错TypeError: Cannot read properties of undefined (reading ‘topModule‘)

轮播图相关属性和样式

detail-swipe

<template>
    <div class="swipe">
        <van-swipe class="swipeList" :autoplay="3000" lazy-render :show-indicators="false">
            <van-swipe-item v-for="item in props.swipeData" :key="item">
                <img :src="item.url" />
            </van-swipe-item>
            <!-- 自定义指示器 -->
            <template #indicator="{ active, total }">
                <div class="custom-indicator">{
   
   { active + 1 }}/{
   
   { total }}</div>
            </template>
        </van-swipe>
    </div>
</template>

<script setup>
const props = defineProps({
      
      
    swipeData: {
      
      
        type: Array,
        default: () => []
    }
})
</script>

<style lang="less" scoped>
.swipe {
      
      

    .swipeList {
      
      
        img {
      
      
            width: 100%;
        }

        .custom-indicator {
      
      
            position: absolute;
            right: 5px;
            bottom: 5px;
            padding: 2px 5px;
            font-size: 12px;
            background: rgba(0, 0, 0, 0.1);
            margin-right: 5px;
            margin-bottom: 5px;
            color: #fff;
        }
    }
}
</style>

detail.vue

<!-- 轮播图 -->
<div class="main" v-if="detailData.mainPart">
    <detailSwipe :swipe-data="detailData.mainPart.topModule.housePicture.housePics"/>
</div>

返回导航栏

NavBar 导航栏 - Vant 4 (gitee.io)

就用这个:
在这里插入图片描述

根据文档,把导航栏NavBar的主题颜色修改一下:(common.css 的 :root)

--van-text-color:var(--primary-color) !important;

注意,此页面是不显示底部的TabBar的,我们要加上top-page类:

/* 隐藏TabBar的类 */
.top-page {
    
    
    /* 占满整个屏幕 */
    height: 100vh;
    /* 有position,z-index才生效
     这里如果是absolute则不生效,可能与TabBar组件相关样式有关 */
    position: relative;
    /* TabBar的z-index默认1 */
    z-index: 9;
    /* 背景色挡住TabBar */
    background-color: #fff;
    /* y轴方向溢出:滚动条 */
    overflow-y: auto;
}

效果

在这里插入图片描述

总代码

修改或添加的文件

在这里插入图片描述

css/common

修改导航栏样式:

:root {
    
    
    /* 主题颜色 */
    --primary-color: #ff9854;
    /* 所有搜索框,有!important才会显示 */
    --van-search-left-icon-color: var(--primary-color) !important;
    /* 所有bottom下划线  */
    --van-tabs-bottom-bar-color: var(--primary-color) !important;

    --van-primary-color:var(--primary-color) !important;
    --van-text-color:var(--primary-color) !important;

    /* 渐变色 */
    --theme-linear-gradient:linear-gradient(90deg,#fa8c1d,#fcaf3f);
}

body {
    
    
    font-size: 14px;
}

/* 隐藏TabBar的类 */
.top-page {
    
    
    /* 占满整个屏幕 */
    height: 100vh;
    /* 有position,z-index才生效
     这里如果是absolute则不生效,可能与TabBar组件相关样式有关 */
    position: relative;
    /* TabBar的z-index默认1 */
    z-index: 9;
    /* 背景色挡住TabBar */
    background-color: #fff;
    /* y轴方向溢出:滚动条 */
    overflow-y: auto;
}

service/modules/detail

detail页面所有的网络请求都在这里。

// 此文件保存所有detail页面的网络请求
import HYRequest from '../request'

export function getDetailInfos(houseId) {
    
    
    return HYRequest.get({
    
    
        url: '/detail/infos',
        params: {
    
    
            houseId
        }
    })
}

service/index

所有的service都在这里。(导入的都是function)

// 此文件导入并导出所有要使用的service

export * from '@/service/modules/city'
export * from '@/service/modules/home'
export * from '@/service/modules/detail'

store/modules/detail

store:管理detail的数据。

import {
    
     defineStore } from "pinia";
import {
    
     getDetailInfos } from '@/service/modules/detail'

const useDetailStore = defineStore('detail', {
    
    
    state: () => {
    
    
        return {
    
    
            detailData: {
    
    },

        }
    },
    actions: {
    
    
        async fetchDetailData(houseId) {
    
    
            const res = await getDetailInfos(houseId)
            // console.log(res)
            this.detailData=res.data
        }
    }
})

export default useDetailStore

views/detail/detail

房屋详情页:

<template>
    <div class="detail top-page">
        <van-nav-bar title="房屋详情" left-text="旅途" left-arrow @click-left="onClickLeft" />

        <!-- 轮播图 -->
        <div class="main" v-if="detailData.mainPart">
            <detailSwipe :swipe-data="detailData.mainPart.topModule.housePicture.housePics" />
        </div>
    </div>
</template>

<script setup>
import useDetailStore from '@/store/modules/detail';
import detailSwipe from '../detail/cpns/detail-swipe.vue'

import {
      
       storeToRefs } from 'pinia';
import {
      
       useRoute } from 'vue-router';

// const
const route = useRoute()
const houseId = route.params.id
const detailStore = useDetailStore()

// store
detailStore.fetchDetailData(houseId)
const {
      
       detailData } = storeToRefs(detailStore)

// navBar
const onClickLeft = () => history.back();
</script>

<style lang="less" scoped>

</style>

views/detail/cpns/detail-swipe

详情页的轮播图组件:

<template>
    <div class="swipe">
        <van-swipe class="swipeList" :autoplay="3000" lazy-render :show-indicators="false">
            <van-swipe-item v-for="item in props.swipeData" :key="item">
                <img :src="item.url" />
            </van-swipe-item>
            <!-- 自定义指示器 -->
            <template #indicator="{ active, total }">
                <div class="custom-indicator">{
   
   { active + 1 }}/{
   
   { total }}</div>
            </template>
        </van-swipe>
    </div>
</template>

<script setup>
const props = defineProps({
      
      
    swipeData: {
      
      
        type: Array,
        default: () => []
    }
})
</script>

<style lang="less" scoped>
.swipe {
      
      

    .swipeList {
      
      
        img {
      
      
            width: 100%;
        }

        .custom-indicator {
      
      
            position: absolute;
            right: 5px;
            bottom: 5px;
            padding: 2px 5px;
            font-size: 12px;
            background: rgba(0, 0, 0, 0.1);
            margin-right: 5px;
            margin-bottom: 5px;
            color: #fff;
        }
    }
}
</style>

main.js

引入新的vant组件。

参考

【前端debug】轮播图报错TypeError: Cannot read properties of undefined (reading ‘topModule‘)

猜你喜欢

转载自blog.csdn.net/karshey/article/details/128871178