前端Vue项目:旅游App-(15)home:网络请求house数据动态并组件化展示house列表信息
Posted karshey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端Vue项目:旅游App-(15)home:网络请求house数据动态并组件化展示house列表信息相关的知识,希望对你有一定的参考价值。
文章目录
本项目博客总结:【前端】Vue项目:旅游App-博客总结
目标
完成热门精选的内容。
- 数据来源:网络请求123.207.32.32:1888/api/home/houselist?page=1
- 把它抽取成组件
过程与代码
content组件
我们将houseList的内容抽取到一个组件中,将其命名为home-content.vue。
<template>
<div class="content">
<h2>热门精选</h2>
<div class="list">
</div>
</div>
</template>
<script setup>
</script>
<style lang="less" scoped>
.content
padding: 0 20px;
h2
font-size: 20px;
font-weight: 700;
</style>
请求数据:houseList
数据是分页的。
第1页:123.207.32.32:1888/api/home/houselist?page=1
第2页:123.207.32.32:1888/api/home/houselist?page=2
以此类推。
本项目已经多此实现对数据请求的功能,因此这里不再赘述。
数据输出:
request
get请求的参数为params,post请求的参数为data。
这里先写死:请求第一页数据。
export function getHouseList()
return HYRequest.get(
url: '/home/houselist',
params:
page: 1
)
store
// home.vue页面所有的进行网络请求和数据都封装到这里
import defineStore from "pinia";
import getHotSuggest, getCategories, getHouseList from '@/service'
const useHomeStore = defineStore('home',
state: () =>
return
hotSuggest: [],
categories: [],
houseList: [],
,
actions:
// 网络请求,由于返回一个promise,要异步async await
async fetchHotSuggest()
const res = await getHotSuggest()
this.hotSuggest = res.data
// console.log(res)
,
async fetchCategories()
const res = await getCategories()
this.categories = res.data
,
async fetchHouseList()
const res = await getHouseList()
this.houseList = res.data
)
export default useHomeStore
控制台输出
数据请求成功。
动态加载更多列表数据
这里的数据一页只有20条,而我们也在代码中写死参数page=1。
实际上,App中此模块的数据是在下拉过程中加载更多的数据。因此我们要动态地加载数据。
这里要使用Array.push
和...
解构语法。
为什么要解构?
答:网络请求得到的是一个数组,不解构会使store中的数据变成二维数组,这不是我们想要的。
如何动态地加载数据?
我们可以先用一个按钮模拟这个功能,每次点击按钮就加载更多的数据,page的参数可以用currentPage来表示,每点击按钮令currentPage++。currentPage存在store中。
request:
export function getHouseList(currentPage)
return HYRequest.get(
url: '/home/houselist',
params:
page: currentPage
)
store:
// home.vue页面所有的进行网络请求和数据都封装到这里
import defineStore from "pinia";
import getHotSuggest, getCategories, getHouseList from '@/service'
const useHomeStore = defineStore('home',
state: () =>
return
hotSuggest: [],
categories: [],
houseList: [],
currentPage: 1,
,
actions:
// 网络请求,由于返回一个promise,要异步async await
async fetchHotSuggest()
const res = await getHotSuggest()
this.hotSuggest = res.data
// console.log(res)
,
async fetchCategories()
const res = await getCategories()
this.categories = res.data
,
async fetchHouseList()
const res = await getHouseList(this.currentPage)
this.currentPage++
this.houseList.push(...res.data)
)
export default useHomeStore
按钮:
<button @click="moreList()">page++</button>
function moreList()
homeStore.fetchHouseList()
初始状态:说明只请求了第一页数据。
点一次按钮:请求了第二页数据。
注意store中currentPage的代码。它表示的是下一次要请求的页面。
根据F12中的网络
也可以得知请求的数据:
house-item组件
显然house-item可能会在项目中多个地方使用,因此我们要把它单独抽为对应组件:
注意,数据中discoveryContentType
表示不同的展示列表数据的方式。上图左为9,右为3.
思路:
- 在
house-content
判断discoveryContentType
,为3则引入组件house-item-v3
,为9则引入组件house-item-v9
- 在
house-item
中定义props:item - 在
house-content
中传入数据house-item
阶段1:数据传送
数据的传送情况如下:
当前效果:
对应代码:
home-content:
<template>
<div class="content">
<h2>热门精选</h2>
<div class="list">
<template v-for="(item, index) in houseList" :key="item.data.houseId">
<houseItemV9 v-if="item.discoveryContentType === 9" :item="item.data"></houseItemV9>
<houseItemV3 v-else-if="item.discoveryContentType === 3" :item="item.data"></houseItemV3>
</template>
</div>
</div>
</template>
<script setup>
import storeToRefs from "pinia";
import useHomeStore from "../../../store/modules/home";
import houseItemV9 from "../../../components/house-item/house-item-v9.vue";
import houseItemV3 from "../../../components/house-item/house-item-v3.vue";
const homeStore = useHomeStore()
homeStore.fetchHouseList()
const houseList = storeToRefs(homeStore)
console.log(houseList)
</script>
<style lang="less" scoped>
.content
padding: 0 20px;
h2
font-size: 20px;
font-weight: 700;
</style>
house-item-v9:
<template>
<div class="house-item">
<h2>v9 item.houseName</h2>
</div>
</template>
<script setup>
defineProps(
item:
type: Object,
default: () => ()
)
</script>
<style lang="less" scoped>
</style>
house-item-v3:
<template>
<div class="house-item">
<h2>v3 item.houseName</h2>
</div>
</template>
<script setup>
defineProps(
item:
type: Object,
default: () => ()
)
</script>
<style lang="less" scoped>
</style>
阶段2:对着目标写样式
评分使用vant库。Rate 评分 - Vant 4 (gitee.io)
要显示小数。
house-item-v9
效果:
代码:
<template>
<div class="house-item">
<div class="house-inner">
<div class="image">
<img :src="item.image.url" alt="">
</div>
<div class="info">
<div class="summary"> item.summaryText </div>
<div class="name"> item.houseName </div>
<div class="tips">
<div class="stars" >
<van-rate v-model="starValue" readonly allow-half size="12px"/>
</div>
<div class="price">
¥ item.finalPrice
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import ref from 'vue';
const props = defineProps(
item:
type: Object,
default: () => ()
)
const starValue = ref(props.item.commentScore);
</script>
<style lang="less" scoped>
.house-item
// 每个item宽度占屏幕一半
width: 50%;
margin-top: 20px;
.house-inner
// 信息在img上:子绝父相
position: relative;
margin: 5px;
.image
img
width: 100%;
border-radius: 6px;
.info
position: absolute;
bottom: 0;
padding: 8px 10px;
color: #fff;
.summary
font-size: 12px;
.name
// 超过2行就省略号省略...
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin: 5px 0;
.tips
display: flex;
justify-content: space-between;
</style>
house-item-v9:debug
出现了一个问题:4.8分只有4颗星。
控制台报错:
大致意思:modelValue要的是Number而不是String。
查看Vue插件的starValue:是字符串。
因此我们要把它改成Number。
const starValue = ref(Number(props.item.commentScore));
house-item-v3
icon的引入:Icon 图标 - Vant 4 (gitee.io)
效果:
代码:
<template>
<div class="house-item">
<div class="house-inner">
<div class="image">
<img :src="item.image.url" alt="">
</div>
<div class="info">
<div class="location">
<van-icon name="location" color="#808080" />
item.location
</div>
<div class="name"> item.houseName </div>
<div class="summary"> item.summaryText </div>
<div class="price">
<div class="cheap">¥ item.finalPrice </div>
<div class="exp"> item.productPrice </div>
<div class="sale">立减¥ item.productPrice - item.finalPrice
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
defineProps(
item:
type: Object,
default: () => ()
)
</script>
<style lang="less" scoped>
.house-item
width: 50%;
.house-inner
margin: 5px;
.image
img
width: 100%;
border-radius: 6px;
以上是关于前端Vue项目:旅游App-(15)home:网络请求house数据动态并组件化展示house列表信息的主要内容,如果未能解决你的问题,请参考以下文章
前端Vue项目:旅游App-(13)home:热门数据的网络请求store和显示
前端Vue项目:旅游App-(13)home:热门数据的网络请求store和显示
前端Vue项目:旅游App-(14)home+search:搜索按钮及其路由跳转分组数据的网络请求request数据存储store和动态显示
前端Vue项目:旅游App-(14)home+search:搜索按钮及其路由跳转分组数据的网络请求request数据存储store和动态显示