In recent years, front-end technology has been constantly updated, and the emergence of front-end frameworks has also greatly improved the efficiency of our daily development. Under the framework of Vue.js, we can easily implement many commonly used functional components, such as city selectors.
So, how to implement the city selector in Vue? This article will share with you a simple implementation method.
1. Data preparation
Before implementing the city selector, we need to prepare city data. Since there is a lot of city data, we need to use a JSON data format to store it. Here, I provide a JSON data file that you can find online or in other resources.
City data file sample:
[ { "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. Selector component implementation
2.1 Introduction of city data
We need to introduce it in the script part of the component City data:
<script> import cityData from './city-data.json'; export default { // 组件属性和方法 } </script>
2.2 Define the selector component
Since the city selector can be used in multiple places, we can define it as a component. In this component, we need to define some properties and methods.
Attributes:
Method:
<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 Rendering city data
Displaying city data in the selector requires recursive rendering. When rendering, we need to define a function to recursively traverse the city data of each layer. Since the city data may have multiple levels, we need to traverse it recursively. In the code implementation, we use the template defined in the Vue component for rendering.
<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 Complete selector component code
The final city selector component code is as follows:
<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>
3. Use the city selector
in Using the city selector component in the Vue project is very simple. You only need to introduce the city selector component into the page you want to use, and then pass in the corresponding parameters when using it. The following is a code example:
<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>
At this point, we can already use the city selector component in the Vue application. The code of this city selector component is very simple, but it implements the basic city selection function and can be expanded and optimized according to your own needs.
The above is the detailed content of How to implement city selector using Vue?. For more information, please follow other related articles on the PHP Chinese website!