Fork me on GitHub

封装一个通用的国家+省份+城市组件

// 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",
          },
        ]
      },

    ],
  },
]

 

posted @ 2024-05-21 14:27  欢欢11  阅读(12)  评论(0编辑  收藏  举报