Vue 城市联动下拉选择组件实现

在做项目的过程中遇到需要选择城市的表单,需要使得 省市区 三级联动选择。element-ui 中有相关组件,但该组件将三者统一在同一个 select 下拉选择框,使得数据双向绑定时还需要切分数据。故考虑根据实际开发情况封装一个通用的联动下拉选择组件。

组件代码

template

<template>
  <div class="city-select">
    <div>
      <!-- 选择省份时:更新市、区数据 -->
      <select
        v-model="province"
        @change="
          updateCity()
          updateDistrict()
          pushData()
        "
      >
        <option v-for="(item, index) in list" :key="index">{{ item.name }}</option>
      </select>
      <select
        v-model="city"
        @change="
          updateDistrict()
          pushData()
        "
      >
        <option v-for="(item, index) in cityList" :key="index">{{ item.name }}</option>
      </select>
      <select v-model="district" @change="pushData">
        <option v-for="(item, index) in DistrictList" :key="index">{{ item.name }}</option>
      </select>
    </div>
  </div>
</template>

script

// 引入省市区数据
import list from '../../../public/data/cities-code.json' 
export default {
  name: 'city-select',
  data() {
    return {
      list, // 总数据
      province: '北京', // 省
      cityList: [], // 市数据,
      city: '', // 市
      DistrictList: [], // 区数据
      district: '', // 区
    }
  },
  methods: {
    // 根据省的选择更新市数据
    updateCity() {
      this.list.forEach((item) => {
        if (item.name === this.province) {
          this.cityList = item.children
        }
      })
      this.city = this.cityList[0].name
    },
    // 根据市的选择更新区数据
    updateDistrict() {
      this.cityList.forEach((item) => {
        if (item.name === this.city) {
          this.DistrictList = item.children
        }
      })
      this.district = this.DistrictList ? this.DistrictList[0].name : ''
    },
    // 数据变化时将数据传递给调用本组件的父组件 (在省市区数据变化时均触发数据推送)
    pushData() {
      this.$emit('updateData', this.province, this.city, this.district)
    },
  },
  mounted() {
    // this.updateCity()
  },
}

style (sass)

// 默认样式
.city-select {
  select {
    height: 40px;
    width: 175px;
    line-height: 40px;
    border: 1px solid #e5e5e5;
    padding: 0 10px;
    margin-right: 15px;
  }
}
使用方法
  1. 引入组件
import CitySelect from '@/components/module/CitySelect.vue'
  1. 使用组件
<city-select @updateData="updateData"></city-select>
  1. 获取数据并使用
updateData(province, city, district) {
  this.receiverProvince = province
  this.receiverCity = city
  this.receiverDistrict = district
},
效果展示

城市选择效果展示

组件特点
  1. 省市区联动,会自动根据上一级选择筛选对应的子级可选项
  2. 选择省份会自动填充默认 市、区
使用注意事项
  1. 导入城市数据格式要求:
    [{name: '某某省', children: [...]}, {...}, ...]
  2. 本组件设置有默认样式,如需更改,在父组件中通过 /deep/ 样式穿透进行设置。例如
    .city-select /deep/ select {......}
遇到的问题及解决方案
  1. 引用该组件往往需要进行双向数据绑定,但绑定的数据存在于子组件,需要使用数据的是父组件。故考虑使用 $emit 进行数据传输,在数据变化时将省市区三个数据同时传递给父组件,并在父组件接收并使用数据
省市区数据来源:

http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/

其他 ❄️

该组件已修改并上传 npm 方便使用
地址:https://www.npmjs.com/package/m-city-select

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue二级联动列表是一种常见的前端交互组件,用于实现两个或多个下列表之间的关联关系。当第一个下列表选择某个选项时,第二个下列表会根据选择的值进行动态更新。 实现Vue二级联动列表的一般步骤如下: 1. 在Vue组件中定义两个数据属性,分别表示第一个和第二个下列表的选中值。 2. 在模板中使用`<select>`标签和`v-model`指令绑定数据属性,实现列表的渲染和选中值的双向绑定。 3. 监听第一个下列表的选中值变化,通过方法或计算属性动态更新第二个下列表的选项。 4. 根据第一个下列表的选中值,筛选或请求相应的数据,更新第二个下列表的选项。 5. 用户选择第二个下列表的选项后,将选中值保存到对应的数据属性中。 以下是一个简单的示例代码: ```html <template> <div> <select v-model="firstSelected" @change="updateSecondOptions"> <option value="">请选择</option> <option v-for="option in firstOptions" :value="option.value" :key="option.value">{{ option.label }}</option> </select> <select v-model="secondSelected"> <option value="">请选择</option> <option v-for="option in secondOptions" :value="option.value" :key="option.value">{{ option.label }}</option> </select> </div> </template> <script> export default { data() { return { firstSelected: '', secondSelected: '', firstOptions: [ { label: '选项1', value: 'option1' }, { label: '选项2', value: 'option2' }, // 其他选项... ], secondOptions: [] }; }, methods: { updateSecondOptions() { // 根据第一个下列表的选中值更新第二个下列表的选项 if (this.firstSelected === 'option1') { this.secondOptions = [ { label: '选项A', value: 'optionA' }, { label: '选项B', value: 'optionB' }, // 其他选项... ]; } else if (this.firstSelected === 'option2') { this.secondOptions = [ { label: '选项X', value: 'optionX' }, { label: '选项Y', value: 'optionY' }, // 其他选项... ]; } else { this.secondOptions = []; } this.secondSelected = ''; // 清空第二个下列表的选中值 } } }; </script> ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值