前端Vue项目:旅游App-(22)detail:房屋信息房屋设施插槽

Posted karshey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端Vue项目:旅游App-(22)detail:房屋信息房屋设施插槽相关的知识,希望对你有一定的参考价值。

文章目录

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

目标

第一个框是房屋信息info,第二个框是房屋设施facility。

过程与代码

房屋信息部分info

目标是这样:


目标数据在整个页面数据的位置:


数据的对应:




因此,我们需要给组件传数据:

detailData.mainPart.topModule

detail.vue:

 <!-- 标题 -->
 <div class="info" v-if="detailData.mainPart">
     <detailInfo :house-info="detailData.mainPart.topModule"/>
 </div>

detail-info对数据的定义:

const props = defineProps(
    houseInfo: 
        type: Object,
        default: () =>  
    
)

根据目标搭建结构:

<template>
    <div class="info">
        <div class="name"> props.houseInfo.houseName </div>
        
        <div class="tag">
            <template v-for="(item,index) in houseTags" :key="index">
                <!-- 注意,有的房屋详情可能没有tagText -->
                <span class="item1" v-if="item.tagText" :style=" color:  item.tagText.color ,background:item.tagText.background.color "> item.tagText.text </span>
                <span class="item1" v-else>
                    <img :src="item.tagPic" alt="">
                </span>
            </template>
        </div>

        <div class="comment item2">
            <div class="score"> commentBrief.overall </div>
            <div class="content"> commentBrief.commentBrief </div>
            <div class="more"> commentBrief.totalCount 条评论></div>
        </div>

        <div class="location item2">
            <div class="content"> nearByPosition.address </div>
            <div class="more">地图 周边></div>
        </div>
    </div>
</template>

<script setup>
const props = defineProps(
    houseInfo: 
        type: Object,
        default: () =>  
    
)

const houseTags = props.houseInfo.houseTags
const commentBrief=props.houseInfo.commentBrief
const nearByPosition=props.houseInfo.nearByPosition

</script>

<style lang="less" scoped>

</style>

效果:


加入样式:

.info 
    .name 
        color: #333;
        font-size: 20px;
        font-weight: 700;
        text-align: justify;
        margin-bottom: 6px;
        letter-spacing: 0.3px;
    

    .tag 

        display: flex;
        flex-wrap: wrap;

        .item1 
            height: 14px;
            margin: 0 3px 3px 0;
            padding: 2px 4px;
            font-size: 12px;

            img 
                height: 18px;
            
        
    

    .item2
        display: flex;
        align-items: center;
        justify-content: space-between;

        margin: 12px 0;
        padding: 8px 12px;
        background-color: #f5f7fa;


        .score
            font-weight: 700;
        
        .address
            font-weight: 700;
        
        .more
            color: var(--primary-color);
        

    

效果:

相似结构的组件section

接下来要做的内容如下:


显然,它们的结构是相似的,可以把它们抽取为一个组件,中间不同的地方是插槽slot

此组件的结构和样式代码:

<template>
    <div class="section">
        <div class="header">
            <h2 class="title"> headerText </h2>
        </div>
        <div class="content">
            <slot>默认内容</slot>
        </div>
        <div class="footer" v-if="moreText.length">
             moreText 
            <van-icon name="arrow" />
        </div>
    </div>
</template>

<script setup>
defineProps(
    headerText: 
        Object: String,
        default: "默认标题"
    ,
    moreText: 
        Object: String,
        default: ""
    
)
</script>

<style lang="less" scoped>
.section 
    margin-top: 10px;
    padding: 0 16px;

    .header 
        height: 52px;
        line-height: 52px;

        h2 
            color: #333;
            font-size: 20px;
            font-weight: 600;
        
    

    .footer
        display: flex;
        justify-content: flex-end;
        align-items: center;

        padding: 0 16px;
        color: var(--primary-color);
        font-weight: 600;
    

</style>

效果:

房屋设施facility

目标:


根据前面组件section代码可知,我们只需要写content的内容,至于header和footer,只需要传入数据即可。

分析一下数据:框起来的是我们要显示的数据。



具体显示情况:要显示houseFacilitys[facilitySort]中数据。

<!-- 内容 -->
<detailSection :header-text="'房屋设施'" :more-text="'全部房屋设施'">
    <!-- 插槽内容 -->
    <detailFacility :houseFacility="detailData.mainPart.dynamicModule.facilityModule.houseFacility" />
</detailSection>

把传给facility组件的对象打印出来:


接下来就是根据数据搭建html结构:

<template>
    <div class="facility">
        <template v-for="(itemIndex, index) in facilitySort" :key="index">
            <div class="item1">
                <!-- 左侧title -->
                <div class="groupName">
                    <img :src="houseFacilitys[itemIndex].icon" alt="">
                     houseFacilitys[itemIndex].groupName 
                </div>
                <div class="nameList">
                    <!-- 右侧最多四个name -->
                    <template v-for="(item, indexx) in houseFacilitys[itemIndex].facilitys.slice(0, 4)" :key="indexx">
                        <van-icon name="passed" /> item.name 
                    </template>
                </div>
            </div>
        </template>
    </div>
</template>

<script setup>
const props = defineProps(
    houseFacility: 
        type: Object,
        default: () => ()
    
)

const facilitySort = props.houseFacility.facilitySort
const houseFacilitys = props.houseFacility.houseFacilitys


</script>

<style lang="less" scoped>

</style>

效果:


注意:数据中右边的每个小item最多只有4个,因此要把要循环的数组先切割为只有4个的:

<template v-for="(item, indexx) in houseFacilitys[itemIndex].facilitys.slice(0,4)" :key="indexx">

加样式:

detail-facility:

.facility 
    background-color: #f7f9fb;
    color: #333;
    padding: 5px 16px 20px;
    border-radius: 6px;

    .item1 
        display: flex;
        align-items: center;
        margin-top: 20px;

        .left 
            display: flex;
            flex-direction: column;
            align-items: center;
            width: 70px;

            .groupName 
                font-weight: 600;
                font-size: 11px;
                margin-top: 3px;
            


            img 
                width: 20px;
                height: 20px;
            
        

        .nameList 
            display: grid;
            grid-template-columns: auto auto ;
            grid-template-rows: auto auto;
            margin-left: 17px;

            .item2 
                width: 110px;
                height: 14px;

                margin-top: 7px;
            
        
    

detail-section:

.section 
    margin-top: 10px;
    padding: 0 16px;

    .header 
        height: 52px;
        line-height: 52px;
        border-bottom: 1px solid  #DCDCDC;

        h2 
            color: #333;
            font-size: 20px;
            font-weight: 600;
        
    

    .content

        margin-top: 20px;
    

    .footer
        display: flex;
        justify-content: flex-end;
        align-items: center;

        padding: 15px 16px;
        color: var(--primary-color);
        font-weight: 600;
    

效果:

效果

总代码

修改或添加的文件

detail-section

将有相似结构的内容抽取出来,不同的部分用插槽实现。

<template>
    <div class="section">
        <div class="header">
            <h2 class="title"> headerText </h2>
        </div>
        <div class="content">
            <slot>默认内容</slot>
        </div>
        <div class="footer" v-if="moreText.length">
            查看 moreText 
            <van-icon name="arrow" />
        </div>
    </div>
</template>

<script setup>
defineProps(
    headerText: 
        Object: String,
        default: "默认标题"
    ,
    moreText: 
        Object: String,
        default: ""
    
)
</script>

<style lang="less" scoped>
.section 
    margin-top: 10px;
    padding: 0 16px;

    .header 
        height: 52px;
        line-height: 52px;
        border-bottom: 1px solid  #DCDCDC;

        h2 
            color: #333;
            font-size: 20px;
            font-weight: 600;
        
    

    .content

        margin-top: 20px;
    

    .footer
        display: flex;
        justify-content: flex-end;
        align-items: center;

        padding: 15px 16px;
        color: var(--primary-color);
        font-weight: 600;
    

</style>

detail-facility

插槽:房屋设施 这一内容组件。

<template>
    <div class="facility">
        <template v-for="(itemIndex, index) in facilitySort" :key="index">
            <div class="item1">
                <!-- 左侧title -->
                <div class="left">
                    <img :src="houseFacilitys[itemIndex].icon" alt="">
                    <div class="groupName"> houseFacilitys[itemIndex].groupName </div>
                </div>
                <div class="nameList">
                    <!-- 右侧最多四个name -->
                    <template v-for="(item, indexx) in houseFacilitys[itemIndex].facilitys.slice(0, 4)" :key="indexx">
                        以上是关于前端Vue项目:旅游App-(22)detail:房屋信息房屋设施插槽的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

前端Vue项目:旅游App-(25):移动端适配

前端Vue项目:旅游App-(20)home:点击跳转至带参数的动态路由

前端Vue项目:旅游App-(19)loading:网络请求时显示loading效果