又双叒一个uniapp组件
最近有一个选择地址的需求,就写了一个省市区联动选择器。
选择日期使用的picker,就照着它简单的整了一个,使用网络请求城市数据,还用到了vuex组件数据共享。
本来自己整了一个底部弹窗,又在插件市场看到了更好的底部弹窗 :LuPopupWrapper--弹窗容器, 所以就用了这个。
依然发布到了插件市场:http://ext.dcloud.net.cn/plugin?id=708
看一下效果吧
具体实现
css就不贴出来了,下载可以看到。
第一、底部弹出框
<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>
这里的底部弹出框用了插件市场的,简单的看一下布局。
slot插槽用于填充弹出框的内容。
最主要的就是弹出和关闭。属性就一个height,控制弹出的高度,其他的暂时不需要。
第二、上下滑动选择城市信息
分析一波:头部两个按钮,取消和确定。头部下面是选择的城市信息展示。再往下就是最重要的选择操作区。
选择操作区分成三列,三列分别显示省市区,并且可滑动。当点击选择后,变为红色。
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)=>{ }); },
第三、网络请求
看官方文档的网络请求后封装一下
//网络请求 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; } }
最后:很简单的一个组件,刚刚开始,希望大家多多包涵,共同学习。