vue.js原生实现这样的地区级联动选择器????

实现效果如图:

<template>
<!--    地区选择-->
    <div class="distpicker" @click.stop>
        <div class="input-text" :class="{selectActive:multistageFlag}" @click="toSelectArea">
            <div>
                <span>{
   
   {country}}</span>
                <span>{
   
   {province}}</span>
                <span>{
   
   {city}}</span>
            </div>
            <span class="select-icon icon icon-arrow-down" :class="{iconActive:multistageFlag}"></span>
        </div>
        <div class="multistage" v-if="multistageFlag">
            <div class="options country-options" v-show="countryFlag">
                <ul>
                    <li class="select-options"  v-for="(cony,index) in areaList" :key="index"
                        :class="{active:country === cony.name}"
                        @click="selectCountry(cony.id, true)">
                        <span>{
   
   {cony.name}}</span>
                        <span v-if="cony.children.length>0" class="icon icon-fanhui"></span>
                    </li>
                </ul>
            </div>
            <div class="options province-options" v-show="provinceFlag">
                <label class="search-field">
                    <input type="text" v-model.trim="searchProvince" @keyup.enter="toSearchProvince"
                           placeholder="请输入搜索内容" autofocus>
                    <span class="icon icon-search" @click="toSearchProvince"></span>
                </label>
                <ul>
                    <li class="select-options" v-for="(pro,index) in provinceList" :key="index"
                        :class="{active:province === pro.name}"
                        @click="selectProvince(pro.id, true)">
                        <span>{
   
   {pro.name}}</span>
                        <span v-if="pro.children.length>0" class="icon icon-fanhui"></span>
                    </li>
                </ul>
            </div>
            <div class="options city-options" v-if="cityFlag">
                <label class="search-field">
                    <input type="text" v-model.trim="searchCity" @keyup.enter="toSearchCity"
                           placeholder="请输入搜索内容" autofocus>
                    <span class="icon icon-search" @click="toSearchCity"></span>
                </label>
                <ul>
                    <li class="select-options" v-for="(cty,index) in cityList" :key="index"
                        :class="{active:city === cty.name}"
                        @click="selectCity(cty.id)">
                        <span>{
   
   {cty.name}}</span>
                    </li>
                </ul>
            </div>
        </div>
        <div class="btn-wrapper" v-if="btnFlag">
            <button class="btn btn-md btn-theme-border" @click="selectResult(1)" :disable="country===''">取消</button>
            <button class="btn btn-md btn-theme" @click="selectResult(2)" :disable="country===''">确定</button>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'regionalLinkage',
        data() {
            return {
                multistageFlag:false,//多级联动显隐
                country: '不限',//国家
                province:'',//省份
                city:'',//城市
                // areaList:[
                //     {name: '不限',id:'', children:[]},
                //     {
                //         name:'中国', id:'中国',
                //         children:[
                //             {
                //                 name:'四川',id:'四川', parentId:'中国',
                //                 children:[
                //                     {name:'凉山',id:'凉山',parentId:'四川'},
                //                     {name:'资阳',id:'资阳',parentId:'四川'},
                //                     {name:'成都',id:'成都',parentId:'四川'},
                //                 ]
                //             },
                //             {
                //                 name:'重庆',id:'重庆',
                //                 children:[
                //                     {name:'酉阳',id:'酉阳',parentId:'重庆'},
                //                     {name:'彭水',id:'彭水',parentId:'重庆'},
                //                 ]
                //             },
                //             {
                //                 name:'陕西', id:'陕西',
                //                 children:[
                //                     {name:'商洛',id:'商洛',parentId:'陕西'},
                //                     {name:'西安',id:'西安',parentId:'陕西'},
                //                 ]
                //             }
                //         ]
                //     }
                // ],
                countryFlag:false,//国家list显隐
                provinceList:[],//省份list
                provinceFlag:false,//省份list显隐
                cityList:[],//城市list
                cityFlag:false,//城市list显隐

                searchProvince:'',//搜索省份
                searchCity:'',//搜索城市
                currentArea: {}
            };
        },
        component: {},
        watch: {},
        props:{
            areaList:{//城市列表
                type:Array
            },
            lastAreaSelect:{//父组件回传子组件上次选中的地区
                type:Object,
                default:{
                    country:'',
                    province:'',
                    city:''
                }
            },
            btnFlag:{//底部按钮显隐
                type:Boolean,
                default: false
            }
        },
        mounted() {
            if (this.lastAreaSelect.country != '' && this.lastAreaSelect.country != undefined) {
                this.country = this.lastAreaSelect.country;
                this.province = this.lastAreaSelect.province;
                this.city = this.lastAreaSelect.city;
                this.selectCountry(this.lastAreaSelect.country, true);
                this.selectProvince(this.lastAreaSelect.province, true);
                this.selectCity(this.lastAreaSelect.city);
            }
            //点击其他地方下拉菜单收起
            window.addEventListener('click', this.eventListener);
        },
        destroyed() {
            window.removeEventListener('click', this.eventListener);
        },
        methods: {
            toSelectArea() {
                this.currentArea = {
                    country:this.country,
                    province:this.province,
                    city:this.city
                };
                this.multistageFlag = !this.multistageFlag;
                this.countryFlag = true;
                this.searchCity = '';
                this.searchProvince = '';
                this.selectCountry(this.currentArea.country, true);
                this.selectProvince(this.currentArea.province, true);
                this.selectCity(this.currentArea.city);
            },
            /**
             * 选择国家
             * toEmpty 是否清空搜索关键字 true清空 false不清空
             * */
            selectCountry(country, toEmpty) {
                if (toEmpty) {
                    this.searchProvince = '';
                }
                if (country === '') {
                    this.country = '不限';
                } else {
                    this.country = country;
                }
                this.provinceList = [];
                for (let i = 0; i < this.areaList.length; i++) {
                    if (this.areaList[i].id === country) {
                        this.provinceList = this.areaList[i].children;
                    }
                }
                if (this.provinceList.length === 0) {
                    this.provinceFlag = false;
                } else {
                    this.provinceFlag = true;
                }
                this.cityFlag = false;
                this.province  = '';
                this.city = '';
            },
            //选择省份
            selectProvince(province, toEmpty) {
                if (toEmpty) {
                    this.searchCity = '';
                }
                this.province = province;
                this.cityList = [];
                for (let i = 0; i < this.provinceList.length; i++) {
                    if (this.provinceList[i].id === province) {
                        this.cityList = this.provinceList[i].children;
                    }
                }
                if (this.cityList.length === 0) {
                    this.cityFlag = false;
                } else {
                    this.cityFlag = true;
                }
                this.city = '';
            },
            //选择城市
            selectCity(city) {
                this.city = city;
            },
            /**
             * 地区选择结果
             * @param type 1取消选择 2确定选择
             */
            selectResult(type){
                if (type === 1) {
                    //取消
                    this.cityFlag = false;
                    this.provinceFlag = false;
                    this.city = '';
                    this.province = '';
                    this.country = '不限';
                }
                this.$emit('sureAreaSelect',{country:this.country, province:this.province, city:this.city});
                this.searchCity = '';
                this.searchProvince = '';
            },
            //搜索省份
            toSearchProvince(){
                this.selectCountry(this.country, false);
                let keyList = [];
                this.provinceList.forEach((item) => {
                    let key = item.id;
                    if (key.indexOf(this.searchProvince) != -1) {
                        keyList.push(item);
                    }
                });
                this.provinceList = keyList;
            },
            //搜索城市
            toSearchCity() {
                this.selectProvince(this.province, false);
                let keyList = [];
                this.cityList.forEach((item) => {
                    let key = item.id;
                    if (key.indexOf(this.searchCity) != -1) {
                        keyList.push(item);
                    }
                });
                this.cityList = keyList;
            },
            //通用方法 下拉菜单的收起
            eventListener() {
                this.multistageFlag = false;
                this.searchCity = '';
                this.searchProvince = '';
            },
        }
    };
</script>

<style type="text/scss" lang="scss">
    @import '../../../common/scss/base/variables';
    @import '../../../common/scss/base/mixin';
    .drop-list{
        padding: 5px;
    }
    .distpicker{
        width: 100%;
        .input-text{
            width: 200px;
            display: flex;
            justify-content: space-between;
            background-color: #fff;
            padding: 0 5px;
            border-radius: 3px;
            border: 1px solid $border-color;
            &.selectActive{
                border-color: $green;
            }
            .select-icon{
                &.iconActive{
                    color: $green;
                }
            }
        }
        .multistage{
            display: flex;
            .options{
                border: 1px solid $border-color;
                background-color: #fff;
                min-width: 210px;
                flex-shrink: 1;
                .select-options{
                    display: flex;
                    justify-content: space-between;
                    cursor: pointer;
                    padding: 0 5px;
                    &.active{
                        background-color: $select-bg;
                    }
                }
                .search-field {
                    position: relative;
                    display: flex;
                    align-items: center;
                    height: $input-field-height;
                    border-bottom: 1px solid $select-border;
                    background-color: $title-bg;
                    @include border-radius(0);
                    color: $color-light-content;

                    input {
                        height: $input-field-height;
                        padding: 0 8px 0 28px;
                        width: 100%;
                        min-width: 5em; // 否则placeholder显示不全
                        border: none;
                        background-color: transparent;

                        &:hover {
                            background-color: $select-bg;

                            & + .icon-search {
                                background-color: $select-bg;
                            }
                        }

                        &:focus {
                            background-color: #fff;

                            & + .icon-search {
                                background-color: #fff;
                            }
                        }
                    }

                    .icon-search {
                        $offset: ($input-field-height - 14px) / 2;
                        position: absolute;
                        width: 26px;
                        height: $input-field-height - 2px;
                        line-height: $input-field-height;
                        text-align: center;
                        left: 1px;
                        top: 1px;
                        background-color: transparent;
                    }
                }
            }
        }
        .btn-wrapper{
            display: flex;
            margin: 5px 0;
            justify-content: flex-end;
        }

    }
</style>

猜你喜欢

转载自blog.csdn.net/Sunny_lxm/article/details/108102227