基于uView组件库封装的地址选择弹框组件

在用uniapp做h5页面时,需要一个类似京东的地址选择弹框组件,故基于uView自己动手封装了一个(如若需要做回显,可以绑定v-model,然后监听value的变化;或者直接在调用open方法时从外部传入参数过来,请自行更改)。

组件region-selection页面如下:

<template>
    <u-popup :show="show" :round="10" mode="bottom" @close="close" :closeable="true">
        <view style="height: 500px">
            <view><u--text text="所在地区" margin="30rpx 0" size="18" bold align="center"></u--text></view>
            <!-- 当前选中的地区 -->
            <view class="hasSelected">
                <view v-for="(item, index) in result" :key="index" :class="index === current ? 'item active' : 'item'"
                    @click="resultChange(item, index)">{{ item.label }}</view>
            </view>
            <!-- 地区数据展示区 -->
            <view>
                <u-list showScrollbar height="380px" v-if="!isFail">
                    <u-list-item v-for="(item, index) in list" :key="index">
                        <u-cell @click="listChange" :name="JSON.stringify(item)">
                            <view slot="title">
                                <u--text :suffixIcon="result[current].value === item.dmbm ? 'checkbox-mark' : ''"
                                    iconStyle="font-size: 25px;color:#f56c6c;margin-left:30rpx;" :text="item.dmmc"
                                    size="18" :bold="result[current].value === item.dmbm"></u--text>
                            </view>
                        </u-cell>
                    </u-list-item>
                </u-list>
                <u-empty v-else mode="data" text="请求失败">
                    <u-button @click="refresh" type="primary" class="mt-20">重新请求</u-button>
                </u-empty>
            </view>
        </view>
    </u-popup>
</template>

<script>
/**
 * @Date 2024-03-01
 * @Description 基于uView(https://www.uviewui.com/components/intro.html)组件封装的地区选择组件
 */
import { getXzqhList } from '@/common/api/common';

export default {
    name: 'region-selection',
    props: {
        // value: {
        //     type: Array,
        //     required: true
        // }
    },
    watch: {
        // value: {
        //     immediate: true,
        //     handler(newValue, oldValue) {
        //         if (newValue && newValue.length > 0) {
        //             this.result = newValue;
        //         } else {
        //             this.result = [{ label: '请选择', value: '' }]
        //         }
        //     }
        // }
    },
    data() {
        return {
            show: false,
            current: 0, //当前在第几层
            result: [{ label: '请选择', value: '', sjdm: '' }],
            list: [],
            isFail: false //控制是否请求失败
        };
    },
    methods: {
        //打开时展示第一层数据
        open() {
            this.show = true;
            this.current = 0;
            getXzqhList()
                .then((res) => {
                    this.isFail = false;
                    this.list = res.data || [];
                })
                .catch(() => {
                    this.isFail = true;
                });
        },
        //点击城市列表
        listChange({ name }) {
            try {
                const item = JSON.parse(name);
                this.result.splice(this.current, 1, { label: item.dmmc, value: item.dmbm, sjdm: item.sjdmbm });
                getXzqhList({ sjdmbm: item.dmbm })
                    .then((res) => {
                        this.isFail = false;
                        this.list = res.data;
                        if (this.list && this.list.length > 0) {
                            //如果还有下一级城市
                            this.result.splice(this.current + 1);
                            this.current++;
                            this.result.splice(this.current, 1, { label: '请选择', value: '', sjdm: '' });
                        } else {
                            //没有下一级城市了
                            this.show = false;
                            this.$emit('ok', this.result);
                            // this.$emit('input', JSON.stringify(this.result));
                        }
                    })
                    .catch(() => {
                        this.isFail = true;
                    });
            } catch (e) { }
        },
        //点击顶部已选择的城市
        resultChange(item, index) {
            if (item.value) {
                this.current = index;
                getXzqhList({ sjdmbm: item.sjdm })
                    .then((res) => {
                        this.isFail = false;
                        this.list = res.data;
                    })
                    .catch(() => {
                        this.isFail = true;
                    });
            }
        },
        //重新加载
        refresh() {
            getXzqhList({ sjdmbm: this.result[this.current].sjdm })
                .then((res) => {
                    this.isFail = false;
                    this.list = res.data;
                })
                .catch(() => {
                    this.isFail = true;
                });
        },
        close() {
            this.show = false;
        }
    }
};
</script>

<style scoped lang="scss">
.hasSelected {
    padding-bottom: 20rpx;
    border-bottom: 1px solid #4b4848;
    .item {
        font-size: 20px;
        display: inline;
        padding: 0 10rpx;
    }
    .active {
        color: #f56c6c;
    }
}
</style>

页面中使用:

<template>
  <packPage>
    <packHeader slot="gHeader" center title="新增地址"></packHeader>
    <view slot="gBody" class="content">
      <view class="contentWrap">
        <u--form labelPosition="left" :model="form" :rules="formRules" labelWidth="90" ref="formRef">
          <u-gap height="8" bgColor="#f6f6f8"></u-gap>
          <u-form-item label="所在地区" prop="xzdxzqhName" required @click="openRegion()" borderBottom>
            <u--input v-model="form.xzdxzqhName" border="none" placeholder="请选择地区" readonly></u--input>
            <u-icon name="arrow-right" slot="right"></u-icon>
          </u-form-item>
          <view style="padding: 5px 10px 0 7px">
            <span style="color: #f56c6c">*</span>
            <span>详细地址</span>
          </view>
          <u-form-item label="" prop="pic1" borderBottom labelWidth="0">
            <u--textarea v-model="form.xxdz" placeholder="请输入详细地址,如小区、写字楼、门牌号等"></u--textarea>
          </u-form-item>
        </u--form>
        <view style="width: 60%; display: flex; margin: 0 auto; padding: 50rpx 0">
          <u-button @click="submit" type="primary" shape="circle">提交</u-button>
        </view>
      </view>
    </view>
    <!--选择住址-->
    <regionSelection ref="regionSelect" @ok="confirmRegion"></regionSelection>
  </packPage>
</template>

<script>
import regionSelection from '@/components/region-selection';
export default {
  components:{regionSelection},
  data() {
    return {
      form: {}
    };
  },
  methods: {
    openRegion(){
      this.$refs.regionSelect.open();
    },
    confirmRegion(data){
      let temp='';
      data.map(i=>temp+=i.label)
      this.$set(this.form, 'xzdxzqhName', temp);
    }
  }
};
</script>

地址选择组件内部只调用了一个接口,通过传入上级城市代码一层一层调用,第一层接口返回格式如下:

{
    "code": 200,
    "msg": "操作成功",
    "data": [
        {
            "dmbm": "494",
            "xzqhdm": "110000",
            "dmmc": "北京市",
            "sm": "北京市",
            "dsm": null,
            "xqm": null,
            "sjdmbm": "0"
        },
        {
            "dmbm": "2955",
            "xzqhdm": "120000",
            "dmmc": "天津市",
            "sm": "天津市",
            "dsm": null,
            "xqm": null,
            "sjdmbm": "0"
        },
        {
            "dmbm": "237",
            "xzqhdm": "130000",
            "dmmc": "河北省",
            "sm": "河北省",
            "dsm": null,
            "xqm": null,
            "sjdmbm": "0"
        },
        {
            "dmbm": "1063",
            "xzqhdm": "140000",
            "dmmc": "山西省",
            "sm": "山西省",
            "dsm": null,
            "xqm": null,
            "sjdmbm": "0"
        },
     ]
   }

效果图如下所示:

基于uView封装的地址选择弹框组件

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值