vue自定义省市区街道选择

vue中自定义选择省、市、区、街道功能,如不需要街道,可自行删除。

这里相关代码没有封装,可自行操作。供参考,欢迎指点。

说明:

  • 所有数据由后端返回。【见末尾效果图】
  • created生命周期中获取数据,当用户点击某得到当前id【父级id】并保存。
  • 根据父级id获取数据。由此类推。


文章目录

  • vue自定义省市区街道选择
  • 效果图
  • template
  • 实现步骤
  • 初始化数据
  • 选择省市区街道事件
  • 点击省市区标题事件
  • 获取地址列表数据
  • style
  • 后端返回数据效果图
  • 数据库结构效果图


效果图

省市区街道mysql数据 省市区json_自定义省市区

template

由于当时项目结合vant组件库,这里底部弹窗应用组件库

<!-- 选择省市区 -->
<div class="van-cell van-field address">
    <div class="van-cell__title van-field__label">门店地址</div>
    <div class="tips" @click="clickProvincesTap">
        <span :class="chooseCity != '请选择' ? 'c' : ''">{{chooseCity == '请选择' ? '请选择' : chooseCity}}</span>
        <img src="../../assets/images/icon/arrow_r.png" alt="">
    </div>
</div>


<!-- 列表展示 -->
<section class="showAddressList">
    <van-action-sheet v-model="showList">
        <div class="titleBox">
            <p></p>
            <p class="title">经营场所地址</p>
            <p class="confirm" @click="showList = false">取消</p>
        </div>
        
        <!-- 省市区街道的标题 -->
        <div class="chooseList">
            <div class="showAddress bd">
                <div class="showArea">
                    <p class="tipTxt" @click="chooseProvince" v-show='tit1'>{{chooseTit1}}</p>
                    <p class="tipTxt" @click="chooseCitys" v-show='tit2'>{{chooseTit2}}</p>
                    <p class="tipTxt" @click="chooseArea" v-show='tit3'>{{chooseTit3}}</p>
                    <p class="tipTxt" v-show='tit4'>{{chooseTit4}}</p>
                </div>
            </div>
            
            <!-- 省市区列表 --->
            <div class="addressList">
                <ul v-show="showProvince">
                    <li v-for="(item, index) in provinceL" :key="item.id" @click="getProvince(item, index)">
                        <div class="items">
                            <div>{{item.name}}</div>
                            <div class="checkIcon" :class="{showIcon: activeIcon1 === index}">
                                <img src="../../assets/images/icon/inquire_ico_check.png" alt="">
                            </div>
                        </div>
                    </li>
                </ul>
                <ul v-show="showCity">
                    <li v-for="(item, index) in cityL" :key="item.id" @click="getCity(item, index)">
                        <div class="items">
                            <div>{{item.name}}</div>
                            <div class="checkIcon" :class="{showIcon: activeIcon2 === index}">
                                <img src="../../assets/images/icon/inquire_ico_check.png" alt="">
                            </div>
                        </div>
                    </li>
                </ul>
                <ul v-show="showArea">
                    <li v-for="(item, index) in areaL" :key="item.id" @click="getArea(item, index)">
                        <div class="items">
                            <div>{{item.name}}</div>
                            <div class="checkIcon" :class="{showIcon: activeIcon3 === index}">
                                <img src="../../assets/images/icon/inquire_ico_check.png" alt="">
                            </div>
                        </div>
                    </li>
                </ul>
                <ul v-show="showStreet">
                    <li v-for="(item, index) in streetL" :key="item.id" @click="getStreet(item, index)">
                        <div class="items">
                            <div>{{item.name}}</div>
                            <div class="checkIcon" :class="{showIcon: activeIcon4 === index}">
                                <img src="../../assets/images/icon/inquire_ico_check.png" alt="">
                            </div>
                        </div>
                    </li>
                </ul>
            </div>
        </div>
    </van-action-sheet>
</section>

实现步骤

初始化数据
<script>
 
    export default {
        name: "addBiz",
        data() {
            return {
                chooseCity: "请选择",
                provinceL: [], //省数据列表
                cityL: [],
                areaL: [],
                streetL: [],
                showProvince: true, //是否显示模块
                showCity: false,
                showArea: false,
                showStreet: false,
                chooseTit1: "请选择省", //占位
                chooseTit2: "请选择市",
                chooseTit3: "请选择区",
                chooseTit4: "请选择街道",
                tit1: true, //切换标题
                tit2: false,
                tit3: false,
                tit4: false,
                province: "", //当前选择值
                Nextcity: "",
                district: "",
                street: "",

                currentType: 1, //当前操作类型 1:省:,2:市,3:区,4:街道
                parentId: 1, //父级id
                currentAdsId: '', //当前选择地址id

                showList: false, //显示地址列表
                activeIcon1: -1, //省 icon状态
                activeIcon2: -1,
                activeIcon3: -1,
                activeIcon4: -1,
            }
        },
        created() {
			// 获取地址省列表
        	this.addressList();
        },
        methods: {
            // 点击选择 省市区 展示弹窗
            clickProvincesTap() {
                this.showList = true;
            },
        }
	}
</script>
选择省市区街道事件

根据当前操作事件得到id获取对应数据,修改相关数据状态。

//当用户点击某个省事件 根据省的id获取市
getProvince(item, index) {
    this.province = item.name;
    this.chooseTit1 = item.name;

    this.activeIcon1 = index; //当前选中icon
    this.currentType = 2;
    this.currentAdsId = item.id;
    this.parentId = item.id;
    //获取地址列表
    this.addressList();
},
//当用户点击某个市事件 根据市的id获取区
getCity(item, index) {
    this.Nextcity = item.name;
    this.chooseTit2 = item.name;

    this.activeIcon3 = -1; //重置icon状态
    this.activeIcon2 = index; //当前选中icon
    this.currentType = 3;
    this.currentAdsId = item.id;
    this.parentId = item.id;
    //获取地址列表
   	this.addressList();
},
//当用户点击某个区事件 根据区的id获取街道
getArea(item, index) {
   	this.district = item.name;
    this.chooseTit3 = item.name;

    this.activeIcon4 = -1;
    this.activeIcon3 = index;
    this.currentType = 4;
    this.currentAdsId = item.id;
    this.parentId = item.id;
    //获取地址列表
    this.addressList();
},
//用户点击镇,隐藏弹窗
getStreet(item, index) {
   	this.street = item.name;
    this.chooseTit4 = item.name;
    this.currentAdsId = item.id;

    this.activeIcon4 = index;
    //获取地址列表
    this.isShowList();
},
//弹窗消失 保存当前选择值
isShowList() {
   	var totalCity = `${this.province}${this.Nextcity}${this.district}${this.street}`;
    this.chooseCity = totalCity;
    this.showList = false;
},
点击省市区标题事件

点击省市区标题时,控制显示/隐藏相关状态

//点击省市区标题显示/隐藏相关内容 形成回退效果
chooseProvince() {
    this.showProvince = true;
    this.showCity = false;
    this.showArea = false;
    this.showStreet = false;

    this.activeIcon2 = -1; //重置
},
chooseCitys() { //选择市
    this.showProvince = false;
    this.showCity = true;
    this.showArea = false;
    this.showStreet = false;

    this.activeIcon3 = -1; //重置
},
chooseArea() { //选择区
   	this.showProvince = false;
    this.showCity = false;
    this.showArea = true;
    this.showStreet = false;
},
获取地址列表数据

根据父级id查询数据,数据请求成功后,根据当前类型修改状态、重置值。

/**
    * 获取地址列表
    */
    addressList() {
        this.loadings('加载中...');
        let that = this;
        let params = {
            type: that.currentType, //当前操作类型
            parent_id: that.parentId //父级id
        };
        this.axios.addressList(params).then(res => {
            that.$toast.clear();
            let datas = res.data;
            if (parseInt(datas.code) != 200) {
                that.$toast(datas.msg);
                return;
            }

            //处理数据
            that.handleByType(datas.data);
        });
    },
    
    //根据当前操作类型处理数据
    handleByType(datas) {
        if(datas.length == 0) {
            this.isShowList();
            return;
        }

        switch(this.currentType) {
            case 1: //省
                this.provinceL = datas;
                break;
            case 2: //市
                this.cityL = datas;
                this.citySelected = this.cityL[0].id;
                this.showProvince = false;
                this.showCity = true;
                this.tit2 = true;

                this.areaL = [];
                break;
            case 3: //区
                this.areaL = datas;
                this.areaSelected = this.areaL[0].id;
                this.showCity = false;
                this.showArea = true;
                this.tit3 = true;

                this.streetL = [];
                break;
            case 4: //街道
                this.streetL = datas;
                this.streetSelected = this.streetL[0].id;
                this.showCity = false;
                this.showArea = false;
                this.showStreet = true;
                this.tit4 = true;
                break;
        }
    }

style

px最终转换为rem单位值,根据需要修改

.showAddressList {
    .titleBox {
        @include wh(100%, 108px);
        @include sc(32px, $fc9);
        @include fcc;
        @include bg(#F4F4F4);
        padding: 0 30px;
        >p {
            flex: 1;
        }
        .title {
            @include sc(36px, $fc);
            text-align: center;
        }
        .confirm {
            color: $main;
            text-align: right;
        }
    }
    .chooseList {
        @include sc(32px, $fc);
        .showAddress {
            @include fc;
            padding: 30px;
            .showArea {
                @include fc;
                p {
                    margin-right: 30px;
                }
            }
            .tipTxt {
                @include sc(32px, $fc9);
                position: relative;
                &::after {
                    content: '';
                    @include cl;
                    bottom: -28px;
                    @include wh(94px, 4px);
                    @include bg($main);
                    @include borderRadius(2px);
                    transition: all 0.1s;
                }
            }
        }
        .bd {
            &::after {
                border-color: #E5E5E5;
                left: 30px;
                right: 30px;
            }
        }
        .addressList {
            ul {
                li {
                    padding: 20px 30px;
                    .items {
                        @include sc(28px, $fc);
                        @include fcb;
                        .checkIcon {
                            @include wh(28px, 20px);
                            @include fcc;
                            display: none;
                            img {
                                @include wh(100%, 100%);
                            }
                        }
                        .showIcon {
                            display: block;
                        }
                    }
                }
            }
        }
    }
}

后端返回数据效果图

根据用户选择: 保存当前操作的id(parent_id参数),调用接口返回相关数据

  • type就是currentType的值【默认是1】: 1—>省,2—>市,3—>区,4—>街道

省市区街道mysql数据 省市区json_数据_02

数据库结构效果图

仅供参考:根据需求定义

  • 例:选择北京市北京市辖区东城区东华门街道

当选择北京对应id2,根据id查询对应。选择对应id3,根据id查询,以此类推。

省市区街道mysql数据 省市区json_ci_03