省市区级联选择框,也可用于其他多层级数据的选择,典型场景为省市区选择。
目前场景设定的是3级,可根据自己的实际需求改成2级或者4级或者更多级。
数据源就是典型的树形结构的JSON数组数据。实际代码中我封装了一个关于省市区三级数据的js插件,具体使用方法
省市区三级行政区划数据JS插件
组件文件area-cascader.stml
- <template>
- <view class="area-cascader_container">
- <view class="area-cascader_box">
- <view class="area-cascader_box-header">
- <text class="area-cascader_box-header-label">请选择所在地区</text>
- <text class="area-cascader_box-header-button" @click="closeCascader">×</text>
- </view>
- <view class="area-cascader_box-nav">
- <view class="area-cascader_box-nav-item" v-for="(item,index) in result" data-index={index} @click="setSelect">
- <text class='area-cascader_box-nav-item--selected' v-if="this.data.selectIndex==index && item.value">{item.text}</text>
- <text class='area-cascader_box-nav-item--unselected' v-else-if="this.data.selectIndex==index && !item.value">请选择</text>
- <text class='area-cascader_box-nav-item--result' v-else-if="this.data.selectIndex!=index && item.value">{{item.text}}</text>
- </view>
- </view>
- <scroll-view class="area-cascader_pane" scroll-y="">
- <view class="area-cascader_pane-option" v-for="(item,index) in selectArea" data-value={item.value} data-text={item.text} @click="setSelectItem">
- <text>{item.text}</text>
- </view>
- </scroll-view>
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'area-cascader',
- props:{
- options:Array
- },
- install(){
- this.data.result[0]={value:null,text:''};
- },
- installed(){
- this.data.selectArea = this.props.options;
- },
- data() {
- return{
- result:[],
- selectIndex:0,
- selectArea:[]
- }
- },
- methods: {
- setSelectItem(e){
- if(this.data.selectIndex<3){
- this.data.result[this.data.selectIndex].value=e.currentTarget.dataset.value;
- this.data.result[this.data.selectIndex].text=e.currentTarget.dataset.text;
- //追加下一级
- this.data.selectIndex+=1;
- if(this.data.selectIndex<3){
- this.data.result[this.data.selectIndex]={value:null,text:''};
- var parentOption=this.data.selectArea.filter(item=>item.value==e.currentTarget.dataset.value);
- this.data.selectArea = parentOption[0].children;
- }
- if(this.data.selectIndex==3){
- this.fire('finish',this.data.result);
- }
- }
- },
- closeCascader(){
- this.fire('close','');
- },
- setSelect(e){
- this.data.selectIndex=e.currentTarget.dataset.index;
- if(this.data.selectIndex==0){
- this.data.selectArea = this.props.options;
- }
- else if(this.data.selectIndex==1){
- var parentOption=this.props.options.filter(item=>item.value==this.data.result[0].value);
- this.data.selectArea = parentOption[0].children;
- }
- }
- }
- }
- </script>
- <style>
- .area-cascader_container {
- position: absolute;
- height: 100%;
- width: 100%;
- background-color: rgba(0,0,0,0.1);
- }
- .area-cascader_box{
- align-items: center;
- position: absolute;
- bottom: 0;
- width: 100%;
- height: 70%;
- background-color: #ffffff;
- border-top-left-radius: 30px;
- border-top-right-radius: 30px;
- }
- .area-cascader_box-header{
- width: 100%;
- flex-flow: row nowrap;
- justify-content: space-between;
- align-items: center;
- padding: 10px 15px 0 15px;
- }
- .area-cascader_box-header-label{
- font-size: 18px;
- }
- .area-cascader_box-header-button{
- font-size: 40px;
- color: #ccc;
- }
- .area-cascader_box-nav{
- width: 100%;
- flex-flow: row nowrap;
- justify-content: flex-start;
- align-items: center;
- padding: 15px;
- }
- .area-cascader_box-nav-item{
- box-sizing: border-box;
- align-items: center;
- /* background-color: #452334; */
- margin-right: 20px;
- justify-content: center;
- }
- .area-cascader_box-nav-item--selected{
- font-size: 16px;
- padding-bottom: 10px;
- border-bottom: 3px solid #49c916;
- }
- .area-cascader_box-nav-item--unselected{
- font-size: 16px;
- padding-bottom: 10px;
- border-bottom: 3px solid #49c916;
- }
- .area-cascader_box-nav-item--result{
- font-size: 16px;
- padding-bottom: 13px;
- border-bottom: 0;
- }
- .area-cascader_pane{
- padding-left: 15px;
- padding-right: 10px;
- width: 100%;
- height: 80%;
- }
- .area-cascader_pane-option{
- flex-flow: row nowrap;
- align-items: flex-start;
- justify-content: space-between;
- padding: 5px 0;
- }
- </style>
复制代码 组件使用
demo-area-cascader.stml
- <template>
- <view class="page">
- <safe-area></safe-area>
- <text style="padding:10px;font-size:20px;">地区级联选择</text>
- <view class="box" @click="openCascader">
- <text>地区</text>
- <text>{selectArea}</text>
- <image class="more" src={ico} mode="widthFix"></image>
- </view>
- <area-cascader
- :options="areaValue"
- onfinish="getArea"
- onclose="closeCascader"
- v-if="isShowCascader"
- >
- </area-cascader>
- </view>
- </template>
- <script>
- import '../../components/area-cascader.stml'
- import {areaList,getTree,getArea,getProvince,getCity} from '../../utils/areaList.js'
- export default {
- name: 'demo-area-cascader',
- apiready(){
- this.data.areaValue = getTree();
- // getCity('130000');
- // getProvince();
- // getArea('130200');
- },
- data() {
- return{
- selectArea:'',
- areaValue:[],
- isShowCascader:false,
- ico:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAZRJREFUeF7t2z1KxEAYgOF3D2Old7AVsdlirS3sBEE9gB5gYQtLC3utxZPYeRgZ2CKEXSGT+X4nqUIgkPfJzBQZsqLzY9V5PwvAMgLsBDbAGjgHPoAHi0exnALvwM0g+hO41kawBNgCT6NgdQRLgAvg+8AbV0WwBCjtZR0o8398qCFYA5gjeAAwRfACYIbgCcAEwRuAOoJHAFUErwBqCJ4BVBC8A4gjRAAQRYgCIIYQCUAEIRpAc4SIAE0RogI0Q4gM0AQhOsBshAwAsxCyAFQjZAKoQsgGMBkhI8B/CK/A/fATdFaAYwi/wEnPAD/AWQ8AxzZcdsBjdoBJu03Z1oBJ8WUkZAKYHJ8JoCo+C0B1fAaAWfHRAWbHRwZoEh8VoFl8RICm8dEAmsdHAhCJjwIgFh8BQDTeO4B4vGcAlXivAGrxHgFU470BqMd7AjCJ9wJgFu8BwDTeGuAS+Bp+ot6fq/0rYA3wBtyOAFTjrQFegOcBgHq8NcDV/qepU6DE3x2YDuKXMu0LVGEtAFVsiW7qfgT8AYVYcEHJaD3BAAAAAElFTkSuQmCC',
-
- }
- },
- methods: {
- getArea(e){
- // console.log(JSON.stringify(e));
- this.data.selectArea = e.detail[0].text+'/'+e.detail[1].text+'/'+e.detail[2].text;
- this.data.isShowCascader = false;
- },
- openCascader(e){
- this.data.isShowCascader = true;
- },
- closeCascader(e){
- this.data.isShowCascader = false;
- }
- }
- }
- </script>
- <style>
- .page {
- height: 100%;
- background-color: #ffffff;
- }
- .box{
- flex-flow: row nowrap;
- justify-content: space-between;
- align-items: center;
- margin: 10px;
- border-radius: 5px;
- background-color: #f0f0f0;
- padding: 10px;
- }
- .more{
- width: 20px;
- }
- </style>
复制代码 使用示例