【前端】Vue项目:旅游App-(9)city:固定tab栏、内容中显示数据

目标

上一篇获取了服务器中的数据:【前端】Vue项目:旅游App-(8)city:标签页Tabs动态数据:网络请求axios与request、数据管理store与pinia、各种封装

本篇目标:显示这些数据。

效果如下:(把两张图拼在一起了)

在这里插入图片描述

过程与代码

Tab一直显示的两种方法

我们把city.vue划分为两部分,top和content。
top部分是要一直显示的搜索框和tab栏,content部分是要显示的数据内容。

下面介绍两种一直显示top的方法。

方法1:fixed定位

我们可以把top栏定位为fixed,让它固定在屏幕的上面。

css:

.top{
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
}

写一点内容:

<div class="content">
    <template v-for="item in 100">
        <div>{{ item }}</div>
    </template>
</div>

效果:

在这里插入图片描述
显然出现了问题:1-7的部分会被遮盖住。

我们令content从top下面开始:

.content{
    margin-top: 98px;
}

效果:好。

在这里插入图片描述

方法2:设置height和overflow-y(效果不好)

直接设置content的height,并令overflow-y为auto,则会在content部分自动产生滚动条。

.content {
    height: calc(100vh-98px);
    overflow-y: auto;
}

效果:竟然出现了两个滚动条,还有一个穿到了Tab栏。这个效果不好,我们不用它。我们只需知道可以有这两种方法即可。(在一些情况下这种方法比上种方法好,视情况而定)

在这里插入图片描述

content显示数据

我们先观察一下数据的结构:

data分为cityGroup和cityGroupOverSea,分别表示国内数据和国外数据,正好对应两个Tab的content显示。这两个对象的结构是相似的。

以cityGroup为例,它是一个对象。我们要显示的数据是cities。

因此,想要拿到数据,我们要用key去找到它们。

在这里插入图片描述
我们观察之前写的代码,我们v-model绑定了一个属性TabActive:

<van-tabs v-model:active="TabActive">
    <template v-for="(value, key, index) in allCity">
        <van-tab :title="value.title"></van-tab>
    </template>
</van-tabs>

根据vant文档,它绑定的是索引值:
在这里插入图片描述
然而,我们要显示的数据是对象的属性,用索引去找数据是很不方便的,我们要想办法获取key

根据文档,有这样一个方法:

在这里插入图片描述
代码:动态绑定属性name,则双向绑定的TabActive属性的值是name,这里我们传入的是key。

<van-tabs v-model:active="TabActive">
   <template v-for="(value, key, index) in allCity">
       <van-tab :title="value.title" :name="key"></van-tab>
   </template>
</van-tabs>

F12,找到vue插件验证一下:确实如此。

在这里插入图片描述
content:

<div class="content">
    <template v-for="item in allCity[TabActive].cities">
        {{ item }}
    </template>
</div>

效果:

在这里插入图片描述
写到这里我们要思考一下,万一有时候我们没有从服务器中拿到数据该怎么办?比如以下情况:

在这里插入图片描述
这时我们会想到ES6的语法可选链运算符?.

在.之前是undefined时不会报错。

currentGroup :注意响应式

// currentGroup:当前选了哪个tab,是key值 
// allCity和TabActive都是响应式,因此要用value取到值
// computed:依赖的东西改变则重新计算,相当于令currentGroup响应式,否则它是写死的(只算一次)
const currentGroup = computed(() => allCity.value[TabActive.value])

template:

<div class="content">
    <template v-for="item in currentGroup?.cities">
        {{ item }}
    </template>
</div>

效果:不报错。

ps:这样写刷新几次之后都能从服务器拿到数据了。好怪…,我以为会有可能拿不到的

效果

在这里插入图片描述

总代码

city.vue

<template>
    <div class="city top-page">
        <div class="top">
            <!-- show-action:显示 “取消”  -->
            <van-search shape="round" v-model="value" show-action placeholder="城市/区域/位置" @search="onSearch"
                @cancel="onCancel" />
            <van-tabs v-model:active="TabActive">
                <template v-for="(value, key, index) in allCity">
                    <van-tab :title="value.title" :name="key"></van-tab>
                </template>
            </van-tabs>
        </div>
        <div class="content">
            <template v-for="item in currentGroup?.cities">
                {{ item }}
            </template>
        </div>
    </div>
</template>

<script setup>
import { computed, ref } from 'vue';
import { showToast } from 'vant';
import useCityStore from '@/store/modules/city'
import { storeToRefs } from 'pinia';

const value = ref('');
const TabActive = ref(0);
const onSearch = (val) => showToast(val);
const onCancel = () => {
    showToast('取消');
}

// tabs的数据
const cityStore = useCityStore()
cityStore.fetchAllCity()
// cityStore是响应式的
const { allCity } = storeToRefs(cityStore)
// console.log(allCity)

// currentGroup:当前选了哪个tab,是key值 
// allCity和TabActive都是响应式,因此要用value取到值
// computed:依赖的东西改变则重新计算,相当于令currentGroup响应式,否则它是写死的(只算一次)
const currentGroup = computed(() => allCity.value[TabActive.value])
</script>

<style lang="less" scoped>
.top {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
}

.content {
    margin-top: 98px;
}
</style>

相关参考

Vue中computed用法
可选链运算符(?.)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值