最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3 + Element Plus 省市區(qū)縣級聯(lián)組件封裝,支持 v-model 雙向綁定 + 回顯,可直接復(fù)用

 更新時間:2026年04月13日 10:14:44   作者:程序媛七分  
本文介紹了如何封裝一個支持省市區(qū)三級聯(lián)動的通用復(fù)用組件,實(shí)現(xiàn)v-model雙向綁定、數(shù)據(jù)回顯、清空、禁用聯(lián)動等功能,提高開發(fā)效率和項(xiàng)目可維護(hù)性,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

在后臺管理系統(tǒng)中,省市區(qū)三級聯(lián)動是非常常見的需求,無論是查詢條件、新增表單、編輯彈窗,都需要用到。

為了避免重復(fù)代碼,提升開發(fā)效率,我們可以把省市區(qū)三級聯(lián)動封裝成一個通用復(fù)用組件,支持:

  • 三級聯(lián)動
  • v-model 雙向綁定
  • 數(shù)據(jù)回顯(編輯頁面必備)
  • 清空、禁用聯(lián)動
  • 多頁面復(fù)用

今天就帶大家一步一步實(shí)現(xiàn)。

全部代碼

<template>
    <div class="region-picker">
        <el-select v-model="provinceId" placeholder="省" clearable style="flex: 1" @change="handleProvinceChange">
            <el-option v-for="item in provinceList" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
        <el-select v-model="cityId" placeholder="市" clearable :disabled="!provinceId" style="flex: 1; margin: 0 8px"
            @change="handleCityChange">
            <el-option v-for="item in cityList" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
        <el-select v-model="districtId" placeholder="區(qū)/縣" clearable :disabled="!cityId" style="flex: 1">
            <el-option v-for="item in areaList" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
    </div>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
// 模擬省市區(qū)數(shù)據(jù)(實(shí)際項(xiàng)目可替換為接口)
const regionData = [
    {
        value: '110000',
        label: '北京市',
        children: [
            {
                value: '110100',
                label: '北京市',
                children: [
                    { value: '110101', label: '東城區(qū)' },
                    { value: '110102', label: '西城區(qū)' },
                    { value: '110105', label: '朝陽區(qū)' },
                    { value: '110106', label: '豐臺區(qū)' },
                    { value: '110108', label: '海淀區(qū)' },
                ]
            }
        ]
    },
    {
        value: '410000',
        label: '河南省',
        children: [
            {
                value: '410100',
                label: '鄭州市',
                children: [
                    { value: '410102', label: '中原區(qū)' },
                    { value: '410103', label: '二七區(qū)' },
                    { value: '410104', label: '管城回族區(qū)' },
                    { value: '410105', label: '金水區(qū)' },
                ]
            },
            {
                value: '410300',
                label: '洛陽市',
                children: [
                    { value: '410302', label: '老城區(qū)' },
                    { value: '410303', label: '西工區(qū)' },
                ]
            }
        ]
    }
]
// 類型定義
interface RegionModel {
    provinceId: string
    cityId: string
    districtId: string
}
// 接收 v-model
const props = withDefaults(defineProps<{
    modelValue?: RegionModel
}>(), {
    modelValue: () => ({ provinceId: '', cityId: '', districtId: '' })
})
// 拋出事件
const emit = defineEmits<{
    'update:modelValue': [value: RegionModel]
    'change': [value: RegionModel]
}>()
// 內(nèi)部選中值
const provinceId = ref('')
const cityId = ref('')
const districtId = ref('')
// 省列表
const provinceList = computed(() => regionData || [])
// 市列表(根據(jù)省動態(tài)計算)
const cityList = computed(() => {
    if (!provinceId.value) return []
    const p = regionData.find(item => item.value === provinceId.value)
    return p?.children || []
})
// 區(qū)縣列表(根據(jù)市動態(tài)計算)
const areaList = computed(() => {
    if (!cityId.value) return []
    const c = cityList.value.find(item => item.value === cityId.value)
    return c?.children || []
})
// 切換省 → 清空市、區(qū)縣
const handleProvinceChange = () => {
    cityId.value = ''
    districtId.value = ''
    emitValue()
}
// 切換市 → 清空區(qū)縣
const handleCityChange = () => {
    districtId.value = ''
    emitValue()
}
// 向外拋出數(shù)據(jù)
const emitValue = () => {
    const value = {
        provinceId: provinceId.value,
        cityId: cityId.value,
        districtId: districtId.value,
    }
    emit('update:modelValue', value)
    emit('change', value)
}
// 監(jiān)聽父組件 v-model 實(shí)現(xiàn)回顯
watch(
    () => props.modelValue,
    (val) => {
        if (val) {
            provinceId.value = val.provinceId || ''
            cityId.value = val.cityId || ''
            districtId.value = val.districtId || ''
        }
    },
    { deep: true, immediate: true }
)
// 監(jiān)聽內(nèi)部變化 → 自動同步父組件
watch([provinceId, cityId, districtId], emitValue)
</script>
<style scoped>
.region-picker {
    display: flex;
    width: 100%;
    gap: 8px;
}
</style>

任意頁面直接調(diào)用??

<template>
  <RegionPicker v-model="queryRegion" @change="handleChange" />
</template>
<script setup>
import RegionPicker from '@/components/RegionPicker/index.vue'
const queryRegion = ref({
  provinceId: '',
  cityId: '',
  districtId: ''
})
const handleChange = (val) => {
  console.log('選中的省市區(qū):', val)
}
</script>

最終達(dá)到的效果

        三級聯(lián)動選擇省自動加載市,選擇市自動加載區(qū)縣

        v-model 雙向綁定父組件直接使用 v-model 綁定

        數(shù)據(jù)回顯:編輯頁面可直接賦值

        自動清空:切換上級,下級自動清空

        禁用聯(lián)動:未選擇上級,下級無法選擇

        支持清空:每個 select 都支持 clearable

        復(fù)用性強(qiáng):查詢表單、彈窗新增、彈窗編輯都能調(diào)用

總結(jié)

封裝成通用組件后,所有頁面只需要寫一行代碼,就能實(shí)現(xiàn)省市區(qū)三級聯(lián)動,大大減少重復(fù)代碼,提升開發(fā)效率和項(xiàng)目可維護(hù)性。

如果需要,還可以擴(kuò)展:

  • 接口動態(tài)獲取省市區(qū)
  • 支持四級聯(lián)動(省市區(qū)街道)
  • 支持默認(rèn)值
  • 支持禁用某項(xiàng)

到此這篇關(guān)于Vue3 + Element Plus 省市區(qū)縣級聯(lián)組件封裝,支持 v-model 雙向綁定 + 回顯,可直接復(fù)用的文章就介紹到這了,更多相關(guān)Vue3 Element Plus 省市區(qū)縣級聯(lián)組件封裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

东乌珠穆沁旗| 宜城市| 卢氏县| 浏阳市| 南充市| 谢通门县| 石嘴山市| 浏阳市| 广东省| 抚宁县| 逊克县| 绥德县| 德化县| 万安县| 两当县| 保康县| 盐津县| 高淳县| 涟水县| 禹州市| 通河县| 芷江| 英吉沙县| 平和县| 扶绥县| 天门市| 大丰市| 平利县| 呼和浩特市| 辽阳县| 永嘉县| 泰州市| 洮南市| 怀化市| 邢台市| 天长市| 石阡县| 菏泽市| 兴文县| 涟源市| 伊川县|