【前端】Vue项目:旅游App-(10)city:以indexBar的形式显示数据

目标

上一篇显示了服务器中的数据:【前端】Vue项目:旅游App-(9)city:固定tab栏、内容中显示数据

本篇目标:将数据展示成这个效果。

在这里插入图片描述

过程与代码

分析数据并展示

首先我们要分析要展示的数据。以国内数据为例:

数据分为citieshotcitiestitle。我们这里要展示的是cities

在这里插入图片描述

cities详情:是一个数组,里面的每一个元素都是一个对象。
每个对象有两个属性:

  • group:表示以本字母开头
  • cities:一个数组,表示以group开头的所有城市

这就是我们要展示的数据。显然需要两层循环。

在这里插入图片描述
在这里插入图片描述
代码:

<div class="content">
  <template v-for="(item,index) in currentGroup?.cities" :key="index">
      <h2 class="title">
          标题{{ item.group }}
      </h2>
      <div class="cities">
          <template v-for="(itemm,indexx) in item.cities" :key="indexx">
              <div class="cityName">
                  {{ itemm.cityName }}
              </div>
          </template>
      </div>
  </template>
</div>

效果:

在这里插入图片描述

封装到一个组件

为了代码的可维护性,封装一下。

currentGroupCity.vue:

<template>
    <template v-for="(item, index) in currentGroup?.cities" :key="index">
        <h2 class="title">
            标题{{ item.group }}
        </h2>
        <div class="cities">
            <template v-for="(itemm, indexx) in item.cities" :key="indexx">
                <div class="cityName">
                    {{ itemm.cityName }}
                </div>
            </template>
        </div>
    </template>
</template>

<script setup>
// 定义数据currentGroup:一个对象
defineProps({
    currentGroup: {
        type: Object,
        default: () => ({})
    }
})
</script>

<style lang="less" scoped>
h2{
    font-size: 20px;
    font-weight: 700;
}
</style>

city.vue把数据传一下:

<div class="content">
   <currentGroupCity :current-group="currentGroup"/>
</div>

添加indexBar

数据已经展示好了,我们还要添加样式。要添加的样式叫做:IndexBar 索引栏 - Vant 4 (gitee.io)

注册好后,根据indexBar的代码进行修改。

在这里插入图片描述
代码:

<template>
    <van-index-bar>
        <template v-for="(item, index) in currentGroup?.cities" :key="index">
            <van-index-anchor :index="item.group" />
            <template v-for="(itemm, indexx) in item.cities" :key="indexx">
                <van-cell :title="itemm.cityName" />
            </template>
        </template>       
    </van-index-bar>
</template>

效果:

在这里插入图片描述
出了一些bug:

Failed to resolve component: van-cell
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.

解决方法:【vue】Failed to resolve component: van-cell If this is a native custom element, make sure to exclude

效果:

在这里插入图片描述

样式修改

把颜色改成主题色橙色。具体步骤见之前的博客,不再赘述。

common.css的:root:

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

还有一件事:我们的滚轮往下滑的时候索引栏会被挡住:

在这里插入图片描述
给类top增加z-index:

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

    // 不被indexBar挡住
    z-index: 9;
}

当然,让它被挡住也行,具体看产品的需求。这里只是写一下如果不让他被挡住的方法。

优化tab栏的切换

写到这里我们发现,每点一次tab栏的切换,数据就会重新加载。这样的效率其实是不高的。

在这里插入图片描述

我们可以这样做:把两份数据都写出来,用v-show显示对应的数据。就像前面对title所做的一样。

<div class="content">
    <template v-for="(value, key, index) in allCity">
        <currentGroupCity v-show="key===TabActive" :current-group="value" />
    </template>
</div>

切换的直观感受:快了一些。虽然数据上差别不大。
在这里插入图片描述

效果

在这里插入图片描述

总代码

修改或新增的文件

在这里插入图片描述

common.css

修改了样式:主题颜色。

:root {
    --van-primary-color:var(--primary-color) !important;
}

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="(value, key, index) in allCity">
                <currentGroupCity v-show="key===TabActive" :current-group="value" />
            </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';
import currentGroupCity from './cpns/currentGroupCity.vue';

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])

console.log(currentGroup)
</script>

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

    // 不被indexBar挡住
    z-index: 9;
}

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

currentGroupCity.vue

循环显示数据的组件。

<template>
    <van-index-bar>
        <template v-for="(item, index) in currentGroup?.cities" :key="index">
            <van-index-anchor :index="item.group" />
            <template v-for="(itemm, indexx) in item.cities" :key="indexx">
                <van-cell :title="itemm.cityName" />
            </template>
        </template>       
    </van-index-bar>
</template>

<script setup>
// 定义数据currentGroup:一个对象
defineProps({
    currentGroup: {
        type: Object,
        default: () => ({})
    }
})
</script>

<style lang="less" scoped>
h2 {
    font-size: 20px;
    font-weight: 700;
}
</style>

main.js

引入组件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

karshey

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

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

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

打赏作者

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

抵扣说明:

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

余额充值