uniapp自定义简单省市区联动组件

又双叒一个uniapp组件css

最近有一个选择地址的需求,就写了一个省市区联动选择器。html

选择日期使用的picker,就照着它简单的整了一个,使用网络请求城市数据,还用到了vuex组件数据共享。vue

原本本身整了一个底部弹窗,又在插件市场看到了更好的底部弹窗 :LuPopupWrapper--弹窗容器, 因此就用了这个。git

依然发布到了插件市场:http://ext.dcloud.net.cn/plugin?id=708github

看一下效果吧vuex

具体实现

css就不贴出来了,下载能够看到。api

第1、底部弹出框
网络

<view class="popup-layout-wrap" :class="popuplayoutClass" >
        <view class="popup-layout-content" :class="popupContentClass" :style="[{height:height}]">
            <slot>
            </slot>
        </view>
        <view v-if="maskShow" class="popup-layout-mask" @tap="close(maskClick)"></view>
</view>

 这里的底部弹出框用了插件市场的,简单的看一下布局。app

slot插槽用于填充弹出框的内容。布局

最主要的就是弹出和关闭。属性就一个height,控制弹出的高度,其余的暂时不须要。

第2、上下滑动选择城市信息

分析一波:头部两个按钮,取消和肯定。头部下面是选择的城市信息展现。再往下就是最重要的选择操做区。

     选择操做区分红三列,三列分别显示省市区,而且可滑动。当点击选择后,变为红色。

html代码

<view class="link-address-wrap">
                <view class="link-adress-content">
                    <view class="head-wrap">
                        <text class="cancel" @click="btn_cancel">取消</text>
                        <text class="confirm" @click="btn_confirm">确认</text>
                    </view>
                    <view class="head-selected">
                        <text class="selected-txt">已选择:{{selected_address}}</text>
                    </view>
                    <view class="operation-wrap">
                        <view class="operation-container">
                            <view class="operation-content">
                                <scroll-view scroll-y="true" class="province" show-scrollbar="false">
                                    <view :class="{'province-txt':index!==province_current,'province-txt-click':index===province_current}" @click="province_txt_click(items.id)" v-model="items.id" v-for="(items , index) of linkAddress_province"
                                        > {{items.name}} <view class="pic" v-show="index===province_current">
                                                <image src="../../static/xuan-linkAddress/yes.png"></image>
                                            </view>
                                    </view>
                                </scroll-view>
                            </view>
                            <view class="operation-content">
                                <scroll-view scroll-y="true" class="province" show-scrollbar="false">
                                    <view :class="{'province-txt':index!==city_current,'province-txt-click':index===city_current}" @click="city_txt_click(items.id)" v-model="items.id" v-for="(items , index) of linkAddress_city"
                                        > {{items.name}} <view class="pic" v-show="index===city_current">
                                                <image src="../../static/xuan-linkAddress/yes.png"></image>
                                            </view>
                                    </view>
                                </scroll-view>
                            </view>
                            <view class="operation-content">
                                <scroll-view scroll-y="true" class="province" show-scrollbar="false">
                                    <view :class="{'province-txt':index!==district_current,'province-txt-click':index===district_current}" @click="district_txt_click(items.id)" v-model="items.id" v-for="(items , index) of linkAddress_district"
                                        > {{items.name}} <view class="pic" v-show="index===district_current">
                                                <image src="../../static/xuan-linkAddress/yes.png"></image>
                                            </view>
                                    </view>
                                </scroll-view>
                            </view>
                        </view>
                    </view>
                </view>
            </view>

 其余的都不用说了,重要的是循环这里。

分为 未点击样式和点击样式。经过点击元素的index和id匹配来切换状态。

须要定义的变量

 data(){ return{ /*省市区选择计数*/ province_current:null, city_current:null, district_current:null, /*省市区循环数据*/ linkAddress_province: [], linkAddress_city: [], linkAddress_district: [], /*请求提交的*/ submission:{ province:'',//
                    city:'',//
                    county:'',//
                    town:''//
 }, /*用户选择的地址*/ user_address:{ province:'',//
                    city:'',//
                    district:''//
 }, selected_address:'' }; }, 

弹窗显示的时候,去请求省的数据。点击省后请求对应省份的市。

js代码 只展现点击省的操做,其余的差很少

//省点击选择
 province_txt_click(target){ //区数据值为空
                this.linkAddress_district= []; //市、区的选择计数置为null
                this.city_current=null; this.district_current=null; let province; //获得点击的数据,改变样式
                for (let i = 0; i < this.linkAddress_province.length; i++) { if (this.linkAddress_province[i].id === target) { this.province_current = i; province=this.linkAddress_province[i].name; break; } } //用户选择
                this.user_address={ province:province, city:'', district:'' } //请求提交的数据先置为空
                this.submission={ province:'', city:'', county:'', town:'' }; //再赋值
                this.submission.province=target; this.selected_address=this.user_address.province; //请求市数据
                linkAddress_p.get_linkAddress(this,"city",this.submission,(revert)=>{ }); }, 

 第3、网络请求

看官方文档的网络请求后封装一下

//网络请求
export default class Request{ /* *paramete 拼接参数 * data 参数值 * method 请求方式 */ http(paramete,data,method){ //根地址
        let BASE_API="http://admin.farmereasy.com"; return new Promise((resolve,reject)=>{ uni.request({ url:`${BASE_API}${paramete}`, data:data, method:method, success:(res)=>{ resolve(res); }, fail:(res)=>{ resolve(0); } }) }); } }

 

import Request from "@/static/xuan-linkAddress/request.js"
//建立Request对象
let request=new Request(); export default{ //data 参数值
    get_linkAddress_api:function(data){ console.log(data); return request.http('/api/address/area',data,'GET'); } }

经过传入不一样标签赋给不一样的变量。

import api from '@/components/xuan-linkAddress/api.js'; export default { /* *_this:全局this * data:数据(参数) * callback:回掉页面 */ get_linkAddress: function(_this,tag,data,callback) { //请求
        api.get_linkAddress_api(data).then((res) => { let revert=res.data.data; console.log(revert) if(res.data.code==1){ if(tag==="province"){ console.log("province") _this.linkAddress_province=revert; callback(true);//回掉
 } if(tag==="city"){ console.log("city") _this.linkAddress_city=revert; callback(true);//回掉
 } if(tag==="district"){ console.log("district") _this.linkAddress_district=revert; callback(true);//回掉
 } } }); } }

组件就完成了,在具体的页面使用

<!-- html-->
   <!-- 用于弹出底部框-->
    <button class="popup-btn" @tap="popup_bottom()">请选择</button>
    <!-- 选择组件 -->
    <linkAddress ref="linkAddress" :height="height" @confirmCallback="confirmCallback()"
        >
    </linkAddress>


  <!-- js--> import linkAddress from '../../components/xuan-linkAddress/xuan-linkAddress.vue' components:{ linkAddress }, methods: { <!-- 点击弹出--> popup_bottom: function() { this.height = '550rpx'; //显示
            this.show_popup(); }, <!-- 显示弹窗--> show_popup: function() { this.$refs.linkAddress.show(); }, <!-- 回掉--> confirmCallback: function() { //从vuex中取到用户选择的数据
            //let ads=this.$store.state.user_address;
            //this.address=ads.province+ads.city+ads.district;
 } }

最后:很简单的一个组件,刚刚开始,但愿你们多多包涵,共同窗习。

GitHub地址:https://github.com/steffenx/uniapp_linkaddress

相关文章
相关标签/搜索