近年來,前端技術不斷更新,前端框架的出現也讓我們日常開發中效率得到很大的提升。在 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>
<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>
<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>
<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 實現城市選擇器?的詳細內容。更多資訊請關注PHP中文網其他相關文章!