vue3+vant4 二次封装IndexBar城市列表组件以及性能优化

前言

二次封装城市列表以及对静态资源的引入做异步引入优化。

版本号: vue3.3 + vant4

效果图

数据源

城市列表 city.json 永久网盘链接

链接:https://pan.baidu.com/s/10E-b441-4P7mjvomlJhm0g

提取码:m92c

字段大致讲解

indexList :每个字母是所属城市外层盒子唯一的key。

van-index-anchor: 是页面的每个标题,例如A、B。

van-cell:title就是A下面的每个城市

进来先用computed把城市数据源中的首个字母取出来。数据源长这个样子

性能优化点

此组件做了一处优化

city.json 同步引入改为异步引入。
作用 :引入的数据量较大时 页面无需因为它而加载不出来,同步的还是照样展示,数据量大的让其加入到异步队列即可,因为我们都知道,同步永远比异步优先执行。
效果:如此可达到快速加载页面、丝毫不影响用户体验,还是挺不错的。

优化前效果图

进入的时候明显要等几秒钟,因为引入方式是同步的,同步需要页面完全加载完才会展示,这是同步引入的弊端。

优化前代码

js 复制代码
<script lang="ts" setup>
import { ref, computed, onMounted} from 'vue'
import { useRouter } from 'vue-router'
import { city } from '@/assets/json/city.json' // 同步导入 JSON 数据

const router = useRouter()
const cityData = city
// const indexList = ['A', 'B', 'C']
//获取所有城市首字母
const indexList = computed(() => {
	return cityData.map(item => item.initial)
})
</script>
优化后效果

立马就进入,依旧优先加载同步,但是city.json改为异步了,已加入异步队列,所以永远在同步后面才执行。

优化后代码

js 复制代码
<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue'
const cityData = ref([])

// const indexList = ['A', 'B', 'C']
//获取所有城市首字母
const indexList = computed(() => {
	return cityData.value.map(item => item.initial)
})

// 异步加载城市数据 性能优化
async function loadCities() {
	try {
		const data = await import('@/assets/json/city.json') // 动态导入 JSON 数据
		cityData.value = data.city // 更新 cities 的值
		// console.log(cityData, 'cityData.value')
	} catch (error) {
		console.error('Failed to load cities:', error)
	}
}

// 在组件挂载后加载数据
onMounted(() => {
	loadCities()
})
</script>

完整源码

City.vue 子组件

js 复制代码
<script lang="ts">
export default {
	name: 'CityList',
}
</script>
<script lang="ts" setup>
import { ref, computed, onMounted, } from 'vue'
import { useRouter } from 'vue-router'

const router = useRouter()
const cityData = ref([])

// const indexList = ['A', 'B', 'C']
//获取所有城市首字母
const indexList = computed(() => {
	return cityData.value.map(item => item.initial)
})

// 选择城市回首页
const backHome = cityname => {
	// router.push({ path: '/', query: { cityname: cityname + '市' } })
	console.log(cityname + '市', '选中的城市')
}
// 异步加载城市数据 性能优化
async function loadCities() {
	try {
		const data = await import('@/assets/json/city.json') // 动态导入 JSON 数据
		cityData.value = data.city // 更新 cities 的值
		// console.log(cityData.value, 'cityData.value')
	} catch (error) {
		console.error('Failed to load cities:', error)
	}
}

// 在组件挂载后加载数据
onMounted(() => {
	loadCities()
})
</script>
<template>
	<div class="city-list-container">
		<div class="hotcity">所有城市</div>
		<van-index-bar :index-list="indexList" highlight-color="#1989fa">
			<div v-for="(city, idx1) in cityData" :key="idx1">
				<van-index-anchor :index="city.initial"></van-index-anchor>
				<van-cell v-for="(item, idx2) in city.list" :key="idx2" :title="item.name" @click="backHome(item.name)"></van-cell>
			</div>
		</van-index-bar>
	</div>
</template>
<style scoped lang="scss">
.hotcity {
	padding: 30px;
	font-size: 28px;
	font-weight: bold;
}
::v-deep(.van-index-bar) {
	background-color: #fff;
}
::v-deep(.van-index-bar__sidebar) {
	top: 72%;
}
</style>

如何使用

以SearchList.vue 父组件为例

js 复制代码
<template>
	<div>
		<CityList />
	</div>
</template>
相关推荐
TimelessHaze26 分钟前
拆解字节面试题:async/await 到底是什么?底层实现 + 最佳实践全解析
前端·javascript·trae
执键行天涯1 小时前
从双重检查锁定的设计意图、锁的作用、第一次检查提升性能的原理三个角度,详细拆解单例模式的逻辑
java·前端·github
青青子衿越1 小时前
微信小程序web-view嵌套H5,小程序与H5通信
前端·微信小程序·小程序
OpenTiny社区1 小时前
TinyEngine 2.8版本正式发布:AI能力、区块管理、Docker部署一键强化,迈向智能时代!
前端·vue.js·低代码
qfZYG1 小时前
Trae 编辑器在 Python 环境缺少 Pylance,怎么解决
前端·vue.js·编辑器
bug爱好者1 小时前
Vue3 基于Element Plus 的el-input,封装一个数字输入框组件
前端·javascript
Silence_xl2 小时前
RACSignal实现原理
前端
柯南二号2 小时前
【大前端】实现一个前端埋点SDK,并封装成NPM包
前端·arcgis·npm
dangkei2 小时前
【Wrangler(Cloudflare 的官方 CLI)和 npm/npx 的区别一次讲清】
前端·jvm·npm
乔公子搬砖2 小时前
小程序开发提效:npm支持、Vant Weapp组件库与API Promise化(八)
前端·javascript·微信小程序·js·promise·vagrant·事件绑定