近年来,前端技术不断地更新,前端框架的出现也让我们日常开发中效率得到很大的提升。在 vue.js 的框架下,我们可以很容易地实现许多常用的功能组件,比如城市选择器。
那么,如何在 Vue 中实现城市选择器呢?本篇文章将给大家分享一个简单的实现方法。
一、数据准备
在实现城市选择器之前,我们需要准备好城市数据。由于城市数据比较多,我们需要使用一个 JSON 数据格式来存储。在这里,我提供了一个 JSON 数据文件,大家可以在网上或其他资源中寻找。
城市数据文件样例:
立即学习“前端免费学习笔记(深入)”;
[
{
"label": "北京市",
"value": "110000",
"children": [
{
"label": "北京市",
"value": "110100",
"children": [
{
"label": "东城区",
"value": "110101"
},
{
"label": "西城区",
"value": "110102"
},
{
"label": "崇文区",
"value": "110103"
},
...
]
}
]
},
{
"label": "上海市",
"value": "310000",
"children": [
{
"label": "上海市",
"value": "310100",
"children": [
{
"label": "黄浦区",
"value": "310101"
},
{
"label": "徐汇区",
"value": "310104"
},
{
"label": "长宁区",
"value": "310105"
},
...
]
}
]
},
...
]二、选择器组件实现
2.1 引入城市数据
我们需要在组件的 script 部分中引入城市数据:
<script>
import cityData from './city-data.json';
export default {
// 组件属性和方法
}
</script>2.2 定义选择器组件
由于城市选择器可以用于多个地方,我们可以将它定义为一个组件。在这个组件中,我们需要定义一些属性和方法。
属性:
方法:
<template>
<div class="city-picker">
<input type="text" :readonly="readonly" :disabled="disabled" :placeholder="placeholder" :style="{width: width}" v-model="selectedCity">
<!-- 其他相关 DOM 结构 -->
</div>
</template>
<script>
import cityData from './city-data.json';
export default {
props: {
modelValue: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请选择城市'
},
width: {
type: String,
default: '200px'
},
disabled: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
selectedCity: this.modelValue,
// 城市数据
cityData: []
}
},
methods: {
handleChangeCity(value) {
this.selectedCity = value;
// 触发父组件的 onChange 事件
this.$emit('onChange', value);
}
},
mounted() {
this.cityData = cityData;
}
}
</script>2.3 渲染城市数据
在选择器中显示城市数据需要进行递归渲染。在渲染时,我们需要定义一个函数,递归遍历每一层的城市数据。由于城市数据可能有多级,我们需要使用递归的方式进行遍历。在代码实现中,我们使用了 Vue 组件中定义的 template 的方式进行渲染。
<template>
<div>
<!-- 递归渲染省份数据 -->
<template v-for="province in cityData">
<div :key="province.value" class="province">
<div @click="handleShowCity(province)">{{ province.label }}</div>
<template v-if="province.children && province.children.length > 0">
<div v-show="province.showCity">
<!-- 递归渲染城市和区县数据 -->
<template v-for="city in province.children">
<div :key="city.value" class="city">
<div @click="handleShowDistrict(city)">{{ city.label }}</div>
<template v-if="city.children && city.children.length > 0">
<div v-show="city.showDistrict">
<div v-for="district in city.children" :key="district.value">{{ district.label }}</div>
</div>
</template>
</div>
</template>
</div>
</template>
</div>
</template>
</div>
</template>
<script>
import cityData from './city-data.json';
export default {
props: {
modelValue: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请选择城市'
},
width: {
type: String,
default: '200px'
},
disabled: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
selectedCity: this.modelValue,
// 城市数据
cityData: []
}
},
methods: {
handleShowCity(province) {
// 点击省份时,展开或关闭城市数据
province.showCity = !province.showCity;
},
handleShowDistrict(city) {
// 点击城市时,展开或关闭区县数据
city.showDistrict = !city.showDistrict;
// 选中城市后,调用 handleChangeCity 方法
this.handleChangeCity(city.label);
},
handleChangeCity(value) {
this.selectedCity = value;
// 触发父组件的 onChange 事件
this.$emit('onChange', value);
},
// 递归遍历城市数据,渲染出每一个层级的城市数据
renderCity(cityData) {
cityData.forEach(city => {
city.showDistrict = false;
if (city.children && city.children.length > 0) {
this.renderCity(city.children);
city.showCity = false;
}
})
}
},
mounted() {
this.cityData = cityData;
// 渲染城市数据
this.renderCity(this.cityData);
}
}
</script>2.4 完整选择器组件代码
最终的城市选择器组件代码如下所示:
<template>
<div class="city-picker">
<input type="text" :readonly="readonly" :disabled="disabled" :placeholder="placeholder" :style="{width: width}" v-model="selectedCity">
<!-- 城市选择器弹出框 -->
<div class="city-picker-modal" v-show="showModal">
<div class="city-picker-header">
<span>请选择城市</span>
<span class="close-icon" @click="handleCloseModal">×</span>
</div>
<div class="city-picker-body">
<!-- 渲染城市选择器树形结构 -->
<div class="city-picker-tree">
<div class="top-tab">
<div
:class="{ active: (activeTab === 'province') }"
@click="handleToggleTab('province')"
>省份</div>
<div
:class="{ active: (activeTab === 'city') }"
@click="handleToggleTab('city')"
>城市</div>
<div
:class="{ active: (activeTab === 'district') }"
@click="handleToggleTab('district')"
>区县</div>
</div>
<div class="tab-content">
<template v-if="activeTab === 'province'">
<!-- 渲染省份数据 -->
<template v-for="province in cityData">
<div :key="province.value" class="province">
<div @click="handleShowCity(province)">{{ province.label }}</div>
<template v-if="province.children && province.children.length > 0">
<div v-show="province.showCity">
<!-- 渲染城市数据 -->
<template v-for="city in province.children">
<div :key="city.value" class="city">
<div @click="handleShowDistrict(city)">{{ city.label }}</div>
<template v-if="city.children && city.children.length > 0">
<div v-show="city.showDistrict">
<!-- 渲染区县数据 -->
<div v-for="district in city.children" :key="district.value">{{ district.label }}</div>
</div>
</template>
</div>
</template>
</div>
</template>
</div>
</template>
</template>
<template v-else-if="activeTab === 'city'">
<!-- 渲染城市数据 -->
<template v-for="province in cityData">
<template v-if="province.children && province.children.length > 0">
<template v-for="city in province.children">
<div :key="city.value" class="city">{{ city.label }}</div>
</template>
</template>
</template>
</template>
<template v-else-if="activeTab === 'district'">
<!-- 渲染区县数据 -->
<template v-for="province in cityData">
<template v-if="province.children && province.children.length > 0">
<template v-for="city in province.children">
<template v-if="city.children && city.children.length > 0">
<template v-for="district in city.children">
<div :key="district.value">{{ district.label }}</div>
</template>
</template>
</template>
</template>
</template>
</template>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import cityData from './city-data.json';
export default {
props: {
modelValue: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请选择城市'
},
width: {
type: String,
default: '200px'
},
disabled: {
type: Boolean,
default: false
},
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
// 当前选中的城市
selectedCity: this.modelValue,
// 城市数据
cityData: [],
// 显示弹出框标志位
showModal: false,
// 当前显示的 tab 标签页
activeTab: 'province'
}
},
methods: {
// 选中省份时,展开或关闭城市数据
handleShowCity(province) {
province.showCity = !province.showCity;
this.activeTab = (province.showCity ? 'city' : 'province');
},
// 选中城市时,展开或关闭区县数据,并选中城市
handleShowDistrict(city) {
city.showDistrict = !city.showDistrict;
this.activeTab = (city.showDistrict ? 'district' : 'city');
this.selectedCity = city.label;
// 触发父组件 onChange 事件
this.$emit('onChange', city.label);
// 关闭弹出层
this.showModal = false;
},
// 切换 tab 标签页
handleToggleTab(tab) {
this.activeTab = tab;
},
// 关闭城市选择器弹窗
handleCloseModal() {
this.showModal = false;
}
},
mounted() {
this.cityData = cityData;
// 递归渲染城市数据,设置状态
this.cityData.forEach((province) => {
province.showCity = false;
if (province.children && province.children.length > 0) {
province.children.forEach((city) => {
city.showDistrict = false;
})
}
})
}
}
</script>三、使用城市选择器
在 Vue 项目中的使用城市选择器组件很简单,只需要在需要使用的页面中引入城市选择器组件,然后在使用时传入相应的参数即可。下面是使用代码示例:
<template>
<div>
<CityPicker
v-model="city"
:width="200"
></CityPicker>
</div>
</template>
<script>
import CityPicker from './components/CityPicker';
export default {
components: {
CityPicker
},
data() {
return {
city: ''
}
},
methods: {
handleChangeCity(value) {
console.log('选中的城市为:', value);
}
}
}
</script>至此,我们已经可以在 Vue 应用中使用城市选择器组件了。这个城市选择器组件代码非常简单,但是实现了基本的城市选择功能,可以依照自己的需求进行扩展和优化。
以上就是如何使用 Vue 实现城市选择器?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号