uniapp开发微信小程序底部地区选择弹框

news/2024/7/7 22:13:03

个人项目地址: SubTopH前端开发个人站

(自己开发的前端功能和UI组件,一些有趣的小功能,感兴趣的伙伴可以访问,欢迎提出更好的想法,私信沟通,网站属于静态页面)

SubTopH前端开发个人站https://subtop.gitee.io/subtoph.github.io/#/home

以上 👆 是个人前端项目,欢迎提出您的建议😊

实现效果

功能介绍:

  1. 支持默认值直接显示滚动定位
  2. 选择上一次后,下一级重置请选择
  3. 选中样式可自定义
  4. 点击确认可校验省市县时候全部选择

 直接上代码模板部分(利用uniapp中的picker-view进一步封装)

<template>
  <view>
    <view
      class="tui-actionsheet-class tui-actionsheet"
      :class="[show ? 'tui-actionsheet-show' : '']"
    >
      <view class="regional-selection">
        <view class="selection-top">
          <text class="top-title">请选择地址区域</text>
          <image
            src="/static/image/bar-close.png"
            class="close-img"
            @tap="handleClickMask"
          />
        </view>
        <view class="selection-title">
          <text>省份</text>
          <text>城市</text>
          <text>区县</text>
        </view>
        <!-- 区域滚动选择 -->
        <picker-view
          class="picker-view"
          indicator-style="height:40px"
          mask-style="background-image: linear-gradient(to top, #ffffffcc,#fff, #fff)"
          @change="bindPickerChange"
          :value="value"
        >
          <!-- 省 -->
          <picker-view-column>
            <view
              class="item"
              :class="{ active: activeProvince === index }"
              v-for="(item, index) in provinces"
              :key="item.key"
              >{{ item.label }}</view
            >
          </picker-view-column>
          <!-- 市 -->
          <picker-view-column>
            <view
              class="item"
              :class="{ active: activeCity === index }"
              v-for="(item, index) in citys"
              :key="item.key"
              >{{ item.label }}</view
            >
          </picker-view-column>
          <!-- 县 -->
          <picker-view-column>
            <view
              class="item"
              :class="{ active: activeCounty === index }"
              v-for="(item, index) in countys"
              :key="item.key"
              >{{ item.label }}</view
            >
          </picker-view-column>
        </picker-view>
        <button type="default" class="confirm-btn" @click="confirmSelect">
          确认
        </button>
      </view>
    </view>
    <!-- 遮罩层 -->
    <view
      class="tui-actionsheet-mask"
      :class="[show ? 'tui-mask-show' : '']"
      @tap="handleClickMask"
    ></view>
  </view>
</template>

javaScript部分代码

<script>
import { reactive, toRefs, onBeforeMount, onMounted, nextTick } from "vue";
import { different } from "@/utils/common.js";
import {
  getEconomize,
  getMarket,
  getCounty,
} from "@/api/modules/common.api.js";   
// 以上省市县的接口,可根据开发实际情况前端写死或者后端请求数据
export default {
  name: "tuiActionsheet",
  props: {
    //点击遮罩 是否可关闭
    maskClosable: {
      type: Boolean,
      default: true,
    },
    //显示操作菜单
    show: {
      type: Boolean,
      default: false,
    },
    // 初始化显示的地区
    currentAddress: {
      type: Array,
    },
  },
  setup(props, ctx) {
    watch(
      () => props.show,
      (val) => {
        if (val) {
          data.provinces = [{ key: "0", label: "请选择" }];
          data.citys = [{ key: "1", label: "请选择" }];
          data.countys = [{ key: "2", label: "请选择" }];
          data.inCurrentAddress = props.currentAddress;
          inGetEconomize();
        }
      }
    );

    const data = reactive({
      inCurrentAddress: [],
      value: [0, 0, 0],
      provinces: [{ key: "0", label: "请选择" }],
      citys: [{ key: "1", label: "请选择" }],
      allCitys: [], //保存已请求的数据
      countys: [{ key: "2", label: "请选择" }],
      allCountys: [],
      activeProvince: 0,
      activeCity: 0,
      activeCounty: 0,
    });
    onBeforeMount(() => {});
    onMounted(() => {});
    // 获取省
    const inGetEconomize = () => {
      // 获取省数据
      getEconomize({ data: {} }).then((res) => {
        if (res.code) return;
        data.provinces.push(...res.data);
        dataHandle("provinces", 0);
      });
    };
    // 获取市
    const inGetCitys = (code) => {
      getMarket({ data: { marketCode: code } }).then((res) => {
        if (res.code) return;
        data.citys.push(...res.data);
        dataHandle("citys", 1);
      });
    };
    // 获取县
    const inGetCountys = (code) => {
      getCounty({ data: { countyCode: code } }).then((res) => {
        if (res.code) return;
        data.countys.push(...res.data);
        dataHandle("countys", 2);
      });
    };
    const dataHandle = (attribute, col) => {
      // data[attribute].unshift();
      const echo = data.inCurrentAddress[col];
      let index = data[attribute].findIndex((item) => item.label === echo);
      index = index < 0 ? 0 : index;
      setActiveStyle(col, index);
      const key = data[attribute][index].key;
      if (col === 0) {
        inGetCitys(key); //获取市
      }
      if (col === 1) {
        inGetCountys(key); //获取县
      }
    };
    // 设置选中值和样式
    const setActiveStyle = (column, index) => {
      nextTick(() => {
        // 设置初始化选中
        data.value[column] = index;
        setActiveValue(data.value);
      });
    };
    // 滚动选择
    const bindPickerChange = (e) => {
      const changeIndex = different(data.value, e.detail.value);
      data.value = e.detail.value;
      setActiveValue(data.value);
      changeSelectHandle(changeIndex);
    };
    const changeSelectHandle = (index) => {
      if (index === 0) {
        data.citys = data.citys.splice(0, 1);
        inGetCitys(data.provinces[data.value[0]].key); //获取市
      }
      if (index === 1) {
        data.countys = data.countys.splice(0, 1);
        if (data.citys.length) {
          inGetCountys(data.citys[data.value[1]].key); //获取县
        }
      }
    };
    // 设置选中项的index控制选中样式
    const setActiveValue = (arr) => {
      data.activeProvince = arr[0];
      data.activeCity = arr[1];
      data.activeCounty = arr[2];
    };
    // 确认选择
    const confirmSelect = () => {
      const { provinces, citys, countys, value } = data;
      const index = value.indexOf(0);
      if (index !== -1) {
        let msg;
        switch (index) {
          case 1:
            msg = "请选择城市";
            break;
          case 2:
            msg = "请选择区县";
            break;
          default:
            msg = "请选择省份";
        }

        uni.showToast({
          icon: "none",
          title: msg,
        });
      } else {
        const confirmArr = [
          provinces[value[0]],
          citys[value[1]],
          countys[value[2]],
        ];
        ctx.emit("confirm", confirmArr);
        handleClickCancel();
      }
    };
    // 点击遮罩层
    const handleClickMask = () => {
      if (!props.maskClosable) return;
      handleClickCancel();
    };
    // 点击取消
    const handleClickCancel = () => {
      ctx.emit("chooseCancel");
    };
    return {
      confirmSelect,
      handleClickMask,
      handleClickCancel,
      bindPickerChange,
      ...toRefs(data),
    };
  },
};
</script>

different方法判断数组中某个值的改变下标

export const different = (arr1, arr2) => {
    let index
    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
            index = i
        }
    }
    return index
}

css样式代码


<style scoped lang="less">
.tui-actionsheet {
  width: 100%;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 9999;
  visibility: hidden;
  transform: translate3d(0, 100%, 0);
  transform-origin: center;
  transition: all 0.3s ease-in-out;
  // background: #eaeaec;
  min-height: 100rpx;
}

.tui-actionsheet-show {
  transform: translate3d(0, 0, 0);
  visibility: visible;
}
.regional-selection {
  position: relative;
  text-align: center;
  height: 818rpx;
  background: #fff;
  border-radius: 32rpx 32rpx 2rpx 2rpx;
  overflow: hidden;
  .selection-top {
    height: 100rpx;
    line-height: 100rpx;
    position: absolute;
    top: 0;
    z-index: 9999;
    width: 100%;
    border-bottom: 1rpx solid #f4f6f9;
    .top-title {
      text-align: center;
      font-size: 30rpx;
      color: #262626;
      font-weight: 600;
    }
    .close-img {
      position: absolute;
      width: 50rpx;
      height: 50rpx;
      right: 24rpx;
      top: 25rpx;
    }
  }
  .selection-title {
    position: absolute;
    top: 100rpx;
    height: 100rpx;
    line-height: 100rpx;
    z-index: 9999;
    width: 100%;
    font-size: 30rpx;
    display: flex;
    color: #262626;
    justify-content: space-around;
  }
  .picker-view {
    width: 750rpx;
    height: 560rpx;
    margin-top: 20px;

    /deep/.uni-picker-view-content {
      padding: 0rpx 0 !important;
    }
    .item {
      height: 40px !important;
      line-height: 40px;
      text-align: center;
      font-size: 26rpx;
      color: #606266;
      font-weight: normal !important;
      &.active {
        color: #0080ff;
        font-size: 30rpx;
      }
    }
  }

  .confirm-btn {
    margin-top: 30rpx;
    height: 88rpx;
    width: 690rpx;
    font-size: 30rpx;
    border-radius: 16rpx;
    line-height: 88rpx;
    background: #0080ff;
    color: #fff;
    &::after {
      border: none;
    }
  }
}

.tui-actionsheet-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 9996;
  transition: all 0.3s ease-in-out;
  opacity: 0;
  visibility: hidden;
}

.tui-mask-show {
  opacity: 1;
  visibility: visible;
}
</style>

效果预览


http://lihuaxi.xjx100.cn/news/1445902.html

相关文章

8,四个类型转换const_cast、reinterpret_cast、dynamic_cast、static_cast

类型转换const_cast、reinterpret_cast、dynamic_cast、static_cast const_castreinterpret_castdynamic_caststatic_cast const_cast 被const修饰的函数可以被访问&#xff0c;但是不能被修改成员变量 const_cast可以去掉const #include <iostream> using namespace s…

一文秒懂HTTP协议到底是什么?原理?

目录 1.什么是http协议&#xff1f; 2.http协议的版本&#xff1f; 3.http文本框架 4.http请求报文 5.http报文格式 6.http响应报文 7.HTTP的状态码 8.HTTP首部介绍 9.什么是URL和URI&#xff1f; 10.CGI是什么&#xff1f; 1.什么是http协议&#xff1f; http&#…

ATF BL1 UFS初始化简单分析

ATF BL1 UFS初始化分析 1 ATF的下载链接2 ATF BL1 UFS 初始化简易流程图3 ATF BL1 ufs初始化简单过程分析3.1 调用过程3.2 hikey960_ufs_init3.3 dw_ufs_init3.3 ufs_init 以海思hikey960为例来介绍&#xff0c;简单介绍在ATF BL1阶段的初始化处理。 1 ATF的下载链接 https:/…

【ARM 嵌入式 编译系列 10.2 -- 符号表与可执行程序分离详细讲解】

文章目录 符号表与可执行程序分离方法一 使用eu-strip方法二 使用 objcopy上篇文章:ARM 嵌入式 编译系列 10.1 – GCC 编译缩减可执行文件 elf 文件大小 下篇文章:ARM 嵌入式 编译系列 10.3 – GNU elfutils 工具小结 符号表与可执行程序分离 接着上篇文章 ARM 嵌入式 编译…

Amazon EMR Hudi 性能调优——Clustering

随着数据体量的日益增长&#xff0c;人们对 Hudi 的查询性能也提出更多要求&#xff0c;除了 Parquet 存储格式本来的性能优势之外&#xff0c;还希望 Hudi 能够提供更多的性能优化的技术途径&#xff0c;尤其当对 Hudi 表进行高并发的写入&#xff0c;产生了大量的小文件之后&…

Vue.js快速入门指南:零基础也能轻松上手,开启前端开发之旅!

目录 MVC设计模式与MVVM设计模式选项式API的编程风格与优势声明式渲染及响应式数据实现原理指令系统与事件方法及传参处理计算属性与侦听器区别与原理条件渲染与列表渲染及注意点class样式与style样式的三种形态表单处理与双向数据绑定原理生命周期钩子函数及原理分析 MVC设计模…

python安装第三方包时报错:...\lib\site-packages\pip\_vendor\urllib3\response.py...

安装redis第三方包&#xff1a; pip install redis报错现象&#xff1a; 解决方法&#xff1a;使用以下命令可成功安装 pip install redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

小白到运维工程师自学之路 第七十三集 (kubernetes应用部署)

一、安装部署 1、以Deployment YAML方式创建Nginx服务 这个yaml文件在网上可以下载 cat nginx-deployment.yaml apiVersion: apps/v1 #apiVersion是当前配置格式的版本 kind: Deployment #kind是要创建的资源类型&#xff0c;这里是Deploymnet metadata: #metadata是该资源…