封装一个通用的国家+省份+城市组件
// AddressSelect.vue <template> <div class="flex-column width100"> <el-row :gutter="8"> <el-col :span="6"> <el-form-item label="" prop="takeOverCountry"> <el-select class="width100" v-model="modelValue.takeOverCountry" clearable filterable placeholder="国家" @change="countryChange"> <el-option v-for="item in countryOption" :key="item.id" :label="item.label" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="" prop="takeOverProvince"> <el-select class="width100" v-model="modelValue.takeOverProvince" clearable filterable placeholder="省份" @change="provinceChange"> <el-option v-for="item in provinceOption" :key="item.id" :label="item.label" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="" prop="takeOverCity"> <el-select class="width100" v-model="modelValue.takeOverCity" clearable filterable placeholder="城市"> <el-option v-for="item in cityOption" :key="item.id" :label="item.label" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="" prop="takeOverPostCode"> <el-input class="width100" clearable v-model="modelValue.takeOverPostCode" placeholder="邮编"></el-input> </el-form-item> </el-col> </el-row> <el-row :gutter="8"> <el-col :span="18"> <el-form-item label="" prop="takeOverAddress"> <el-input style="margin-top: 20px" clearable v-model="modelValue.takeOverAddress" placeholder="详细地址"></el-input> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="" prop="takeOverOther"> <el-input style="margin-top: 20px" clearable v-model="modelValue.takeOverOther" placeholder="门牌号"></el-input> </el-form-item> </el-col> </el-row> </div> </template> <script> import { ref } from 'vue'; export default { props: { treeData: { type: Array, required: true }, modelValue: { type: Object, default: () => ({}) } }, setup(props) { const countryOption = ref(props.treeData); const provinceOption = ref([]); const cityOption = ref([]); const countryChange = (value) => { const selectedCountry = props.treeData.find(country => country.id === value); provinceOption.value = selectedCountry ? selectedCountry.children : []; cityOption.value = []; props.modelValue.takeOverProvince = ''; props.modelValue.takeOverCity = ''; }; const provinceChange = (value) => { const selectedProvince = provinceOption.value.find(province => province.id === value); cityOption.value = selectedProvince ? selectedProvince.children : []; props.modelValue.takeOverCity = ''; }; return { modelValue: props.modelValue, countryOption, provinceOption, cityOption, countryChange, provinceChange } } } </script>
// 使用 <template> <div> <el-form ref="form" :model="form" :rules="rules" label-width="120px"> <address-select v-model="form" :tree-data="treeData" /> <el-button type="primary" @click="submitForm('form')">提交</el-button> </el-form> </div> </template> <script> import AddressSelect from './components/AddressSelect.vue'; import { treeData } from './data.js'; // 导入treeData数据 export default { components: { AddressSelect }, data() { return { treeData, form: { takeOverCountry: '', takeOverProvince: '', takeOverCity: '', takeOverPostCode: '', takeOverAddress: '', takeOverOther: '' }, rules: { takeOverCountry: [{ required: true, message: '请选择国家', trigger: 'change' }], takeOverProvince: [{ required: true, message: '请选择省份', trigger: 'change' }], takeOverCity: [{ required: true, message: '请选择城市', trigger: 'change' }], takeOverPostCode: [{ required: true, message: '请填写邮编', trigger: 'blur' }], takeOverAddress: [{ required: true, message: '请填写详细地址', trigger: 'blur' }], takeOverOther: [{ required: true, message: '请填写门牌号', trigger: 'blur' }] } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); return false; } }); } } }; </script>
export const treeData = [ { id: "Canada", label: "Canada", children: [ { id: "Alberta", label: "Alberta", children: [ { id: "Banff", label: "Banff", }, { id: "Brooks", label: "Brooks", }, { id: "Calgary", label: "Calgary", }, { id: "Edmonton", label: "Edmonton", }, { id: "Fort McMurray", label: "Fort McMurray", }, { id: "Grande Prairie", label: "Grande Prairie", }, { id: "Jasper", label: "Jasper", }, { id: "Lake Louise", label: "Lake Louise", }, { id: "Lethbridge", label: "Lethbridge", }, { id: "Medicine Hat", label: "Medicine Hat", }, { id: "Red Deer", label: "Red Deer", }, { id: "Saint Albert", label: "Saint Albert", }, ], }, { id: "British Columbia", label: "British Columbia", children: [ { id: "Barkerville", label: "Barkerville", }, { id: "Burnaby", label: "Burnaby", }, { id: "Campbell River", label: "Campbell River", }, { id: "Chilliwack", label: "Chilliwack", }, { id: "Courtenay", label: "Courtenay", }, { id: "Cranbrook", label: "Cranbrook", }, { id: "Dawson Creek", label: "Dawson Creek", }, { id: "Delta", label: "Delta", }, { id: "Esquimalt", label: "Esquimalt", }, { id: "Fort Saint James", label: "Fort Saint James", }, { id: "Fort Saint John", label: "Fort Saint John", }, { id: "Hope", label: "Hope", }, { id: "Kamloops", label: "Kamloops", }, { id: "Kelowna", label: "Kelowna", }, { id: "Kimberley", label: "Kimberley", }, { id: "Kitimat", label: "Kitimat", }, { id: "Langley", label: "Langley", }, { id: "Nanaimo", label: "Nanaimo", }, { id: "Nelson", label: "Nelson", }, { id: "New Westminster", label: "New Westminster", }, { id: "North Vancouver", label: "North Vancouver", }, { id: "Oak Bay", label: "Oak Bay", }, { id: "Penticton", label: "Penticton", }, { id: "Powell River", label: "Powell River", }, { id: "Prince George", label: "Prince George", }, { id: "Prince Rupert", label: "Prince Rupert", }, { id: "Quesnel", label: "Quesnel", }, { id: "Revelstoke", label: "Revelstoke", }, { id: "Rossland", label: "Rossland", }, { id: "Trail", label: "Trail", }, { id: "Vancouver", label: "Vancouver", }, { id: "Vernon", label: "Vernon", }, { id: "Victoria", label: "Victoria", }, { id: "West Vancouver", label: "West Vancouver", }, { id: "White Rock", label: "White Rock", }, ] }, { id: "Manitoba", label: "Manitoba", children: [ { id: "Brandon", label: "Brandon", }, { id: "Churchill", label: "Churchill", }, { id: "Dauphin", label: "Dauphin", }, { id: "Flin Flon", label: "Flin Flon", }, { id: "Kildonan", label: "Kildonan", }, { id: "Saint Boniface", label: "Saint Boniface", }, { id: "Swan River", label: "Swan River", }, { id: "Thompson", label: "Thompson", }, { id: "Winnipeg", label: "Winnipeg", }, { id: "York Factory", label: "York Factory", }, ] }, { id: "New Brunswick", label: "New Brunswick", children: [ { id: "Bathurst", label: "Bathurst", }, { id: "Caraquet", label: "Caraquet", }, { id: "Dalhousie", label: "Dalhousie", }, { id: "Fredericton", label: "Fredericton", }, { id: "Miramichi", label: "Miramichi", }, { id: "Moncton", label: "Moncton", }, { id: "Saint John", label: "Saint John", }, ] }, { id: "Newfoundland and Labrador", label: "Newfoundland and Labrador", children: [ { id: "Argentia", label: "Argentia", }, { id: "Bonavista", label: "Bonavista", }, { id: "Channel-Port aux Basques", label: "Channel-Port aux Basques", }, { id: "Corner Brook", label: "Corner Brook", }, { id: "Ferryland", label: "Ferryland", }, { id: "Gander", label: "Gander", }, { id: "Grand Falls–Windsor", label: "Grand Falls–Windsor", }, { id: "Happy Valley–Goose Bay", label: "Happy Valley–Goose Bay", }, { id: "Harbour Grace", label: "Harbour Grace", }, { id: "Labrador City", label: "Labrador City", }, { id: "Placentia", label: "Placentia", }, { id: "Saint Anthony", label: "Saint Anthony", }, { id: "St. John’s", label: "St. John’s", }, { id: "Wabana", label: "Wabana", }, ] }, { id: "Northwest Territories", label: "Northwest Territories", children: [ { id: "Fort Smith", label: "Fort Smith", }, { id: "Hay River", label: "Hay River", }, { id: "Inuvik", label: "Inuvik", }, { id: "Tuktoyaktuk", label: "Tuktoyaktuk", }, { id: "Yellowknife", label: "Yellowknife", }, ] }, { id: "Nova Scotia", label: "Nova Scotia", children: [ { id: "Baddeck", label: "Baddeck", }, { id: "Digby", label: "Digby", }, { id: "Glace Bay", label: "Glace Bay", }, { id: "Halifax", label: "Halifax", }, { id: "Liverpool", label: "Liverpool", }, { id: "Louisbourg", label: "Louisbourg", }, { id: "Lunenburg", label: "Lunenburg", }, { id: "Pictou", label: "Pictou", }, { id: "Port Hawkesbury", label: "Port Hawkesbury", }, { id: "Springhill", label: "Springhill", }, { id: "Sydney", label: "Sydney", }, { id: "Yarmouth", label: "Yarmouth", }, ] }, { id: "Nunavut", label: "Nunavut", children: [ { id: "Iqaluit", label: "Iqaluit", }, ] }, { id: "Ontario", label: "Ontario", children: [ { id: "Bancroft", label: "Bancroft", }, { id: "Barrie", label: "Barrie", }, { id: "Belleville", label: "Belleville", }, { id: "Brampton", label: "Brampton", }, { id: "Brantford", label: "Brantford", }, { id: "Brockville", label: "Brockville", }, { id: "Burlington", label: "Burlington", }, { id: "Cambridge", label: "Cambridge", }, { id: "Chatham", label: "Chatham", }, { id: "Chatham-Kent", label: "Chatham-Kent", }, { id: "Cornwall", label: "Cornwall", }, { id: "Elliot Lake", label: "Elliot Lake", }, { id: "Etobicoke", label: "Etobicoke", }, { id: "Fort Erie", label: "Fort Erie", }, { id: "Fort Frances", label: "Fort Frances", }, { id: "Gananoque", label: "Gananoque", }, { id: "Guelph", label: "Guelph", }, { id: "Hamilton", label: "Hamilton", }, { id: "Iroquois Falls", label: "Iroquois Falls", }, { id: "Kapuskasing", label: "Kapuskasing", }, { id: "Kawartha Lakes", label: "Kawartha Lakes", }, { id: "Kenora", label: "Kenora", }, { id: "Kingston", label: "Kingston", }, { id: "Kirkland Lake", label: "Kirkland Lake", }, { id: "Kitchener", label: "Kitchener", }, { id: "Laurentian Hills", label: "Laurentian Hills", }, { id: "London", label: "London", }, { id: "Midland", label: "Midland", }, { id: "Mississauga", label: "Mississauga", }, { id: "Moose Factory", label: "Moose Factory", }, { id: "Moosonee", label: "Moosonee", }, { id: "Niagara Falls", label: "Niagara Falls", }, { id: "Niagara-on-the-Lake", label: "Niagara-on-the-Lake", }, { id: "North Bay", label: "North Bay", }, { id: "North York", label: "North York", }, { id: "Oakville", label: "Oakville", }, { id: "Orillia", label: "Orillia", }, { id: "Oshawa", label: "Oshawa", }, { id: "Ottawa", label: "Ottawa", }, { id: "Parry Sound", label: "Parry Sound", }, { id: "Perth", label: "Perth", }, { id: "Peterborough", label: "Peterborough", }, { id: "Picton", label: "Picton", }, { id: "Port Colborne", label: "Port Colborne", }, { id: "Saint Catharines", label: "Saint Catharines", }, { id: "Saint Thomas", label: "Saint Thomas", }, { id: "Sarnia-Clearwater", label: "Sarnia-Clearwater", }, { id: "Sault Sainte Marie", label: "Sault Sainte Marie", }, { id: "Scarborough", label: "Scarborough", }, { id: "Simcoe", label: "Simcoe", }, { id: "Stratford", label: "Stratford", }, { id: "Sudbury", label: "Sudbury", }, { id: "Temiskaming Shores", label: "Temiskaming Shores", }, { id: "Thorold", label: "Thorold", }, { id: "Thunder Bay", label: "Thunder Bay", }, { id: "Timmins", label: "Timmins", }, { id: "Toronto", label: "Toronto", }, { id: "Trenton", label: "Trenton", }, { id: "Waterloo", label: "Waterloo", }, { id: "Welland", label: "Welland", }, { id: "West Nipissing", label: "West Nipissing", }, { id: "Windsor", label: "Windsor", }, { id: "Woodstock", label: "Woodstock", }, { id: "York", label: "York", }, ] }, { id: "Prince Edward Island", label: "Prince Edward Island", children: [ { id: "Borden", label: "Borden", }, { id: "Cavendish", label: "Cavendish", }, { id: "Charlottetown", label: "Charlottetown", }, { id: "Souris", label: "Souris", }, { id: "Summerside", label: "Summerside", }, ] }, { id: "Quebec", label: "Quebec", children: [ { id: "Asbestos", label: "Asbestos", }, { id: "Baie-Comeau", label: "Baie-Comeau", }, { id: "Beloeil", label: "Beloeil", }, { id: "Cap-de-la-Madeleine", label: "Cap-de-la-Madeleine", }, { id: "Chambly", label: "Chambly", }, { id: "Charlesbourg", label: "Charlesbourg", }, { id: "Châteauguay", label: "Châteauguay", }, { id: "Chibougamau", label: "Chibougamau", }, { id: "Côte-Saint-Luc", label: "Côte-Saint-Luc", }, { id: "Dorval", label: "Dorval", }, { id: "Gaspé", label: "Gaspé", }, { id: "Gatineau", label: "Gatineau", }, { id: "Granby", label: "Granby", }, { id: "Havre-Saint-Pierre", label: "Havre-Saint-Pierre", }, { id: "Hull", label: "Hull", }, { id: "Jonquière", label: "Jonquière", }, { id: "Kuujjuaq", label: "Kuujjuaq", }, { id: "La Salle", label: "La Salle", }, { id: "La Tuque", label: "La Tuque", }, { id: "Lachine", label: "Lachine", }, { id: "Laval", label: "Laval", }, { id: "Lévis", label: "Lévis", }, { id: "Longueuil", label: "Longueuil", }, { id: "Magog", label: "Magog", }, { id: "Matane", label: "Matane", }, { id: "Montreal", label: "Montreal", }, { id: "Montréal-Nord", label: "Montréal-Nord", }, { id: "Percé", label: "Percé", }, { id: "Port-Cartie", label: "Port-Cartie", }, { id: "Quebec", label: "Quebec", }, { id: "Rimouski", label: "Rimouski", }, { id: "Rouyn-Noranda", label: "Rouyn-Noranda", }, { id: "Saguenay", label: "Saguenay", }, { id: "Saint-Eustache", label: "Saint-Eustache", }, { id: "Saint-Hubert", label: "Saint-Hubert", }, { id: "Sainte-Anne-de-Beaupré", label: "Sainte-Anne-de-Beaupré", }, { id: "Sainte-Foy", label: "Sainte-Foy", }, { id: "Sainte-Thérèse", label: "Sainte-Thérèse", }, { id: "Sept-Îles", label: "Sept-Îles", }, { id: "Sherbrooke", label: "Sherbrooke", }, { id: "Sorel-Tracy", label: "Sorel-Tracy", }, { id: "Trois-Rivières", label: "Trois-Rivières", }, { id: "Val-d’Or", label: "Val-d’Or", }, { id: "Waskaganish", label: "Waskaganish", }, ] }, { id: "Saskatchewan", label: "Saskatchewan", children: [ { id: "Batoche", label: "Batoche", }, { id: "Cumberland House", label: "Cumberland House", }, { id: "Estevan", label: "Estevan", }, { id: "Flin Flon", label: "Flin Flon", }, { id: "Moose Jaw", label: "Moose Jaw", }, { id: "Prince Albert", label: "Prince Albert", }, { id: "Regina", label: "Regina", }, { id: "Saskatoon", label: "Saskatoon", }, { id: "Uranium City", label: "Uranium City", }, ] }, { id: "Yukon", label: "Yukon", children: [ { id: "Dawson", label: "Dawson", }, { id: "Watson Lake", label: "Watson Lake", }, { id: "Whitehorse", label: "Whitehorse", }, ] }, ], }, ]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通