uniapp和vue3+ts创建自定义下拉选择框组件

使用uniapp开发小程序的时候,使用了uview的ui组件,但是里面没有下拉选择组件,只有Picker 选择器,但是我们想要使用下拉选择的组件,所以需要自定义个一个下拉选择的自定义组件,我就只能自己动手创建这个自定义组件了,支持:多选,单选,下拉框在框内还是框外

实现的效果:

自定义组件源代码:Select.vue

<template><!-- <view class="uni-select-dc" :style="{ 'z-index': zindex }"> --><view class="uni-select-dc" :style="{ 'z-index': zindex }"><view class="uni-select-dc-select" :class="{ active: active }" @click.stop="handleSelect"><!-- 禁用mask --><view class="uni-disabled" v-if="disabled"></view><!-- 清空 --><view class="close-icon close-postion" v-if="realValue.length && !active && !disabled && showClearIcon"><text @click.stop="handleRemove(null)"></text></view><!-- 显示框 --><view class="uni-select-multiple" v-show="realValue.length"><view class="uni-select-multiple-item" v-if="multiple" v-for="(item, index) in changevalue" :key="index">{{ item.text }}<view class="close-icon" v-if="showValueClear"><text @click.stop="handleRemove(index)"></text></view></view><!-- 单选时展示内容 --><view v-else class="single-text">{{ changevalue.length ? changevalue[0].text : "" }}</view></view><!-- 为空时的显示文案 --><view v-if="realValue.length == 0 && showplaceholder">{{placeholder}}</view><!-- 右边的下拉箭头 --><view :class="{ disabled: disabled, 'uni-select-dc-icon': !downInner, 'uni-select-dc-inner': downInner }"><text></text></view></view><!-- 下拉选项 --><scroll-view class="uni-select-dc-options" :scroll-y="true" v-show="active"><template><view class="uni-select-dc-item" :class="{ active: realValue.includes((item as any)[svalue]) }"v-for="(item, index) in options" :key="index" @click.stop="handleChange(index, item)">{{ (item as any)[slabel] }}</view></template></scroll-view></view>
</template><script lang="ts" setup>
import { onMounted, reactive, ref } from "vue";const props = defineProps({// 是否显示全部清空按钮showClearIcon: {type: Boolean,default: false,},// 是否多选multiple: {type: Boolean,default: false,},// 下拉箭头是否在框内downInner: {type: Boolean,default: true,},// 是否显示单个删除showValueClear: {type: Boolean,default: true,},zindex: {type: Number,default: 999,},// 禁用选择disabled: {type: Boolean,default: false,},options: {type: Array,default() {return [];},},value: {type: Array,default() {return [];},},placeholder: {type: String,default: "请选择",},showplaceholder: {type: Boolean,default: true,},// 默认取textslabel: {type: String,default: "text",},// 默认取valuesvalue: {type: String,default: "value",},
});
const emit = defineEmits(["change"]);
const active = ref<boolean>(false); // 组件是否激活,
let changevalue = reactive<Record<any, any>>([]);
let realValue = reactive<Record<string, any>>([]);
onMounted(() => {init();
});// 初始化函数
const init = () => {if (props.value.length > 0) {props.options.forEach((item) => {props.value.forEach((i) => {if ((item as any)[props.svalue] === i) {changevalue.push(item);}})})realValue = props.value;console.log("props---", changevalue);} else {changevalue = [];realValue = [];}
};
// 点击展示选项
const handleSelect = () => {if (props.disabled) return;active.value = !active.value;
};
// 移除数据
const handleRemove = (index: any) => {if (index === null) {realValue = [];changevalue = [];} else {realValue.splice(index, 1);changevalue.splice(index, 1);}emit("change", changevalue, realValue);
};
// 点击组件某一项
const handleChange = (index, item) => {console.log("选中了某一项", index, item);// 如果是单选框,选中一项后直接关闭if (!props.multiple) {console.log("关闭下拉框");changevalue.length = 0realValue.length = 0changevalue.push(item);realValue.push(item[props.svalue])active.value = !active.value;} else {// 多选操作const arrIndex = realValue.indexOf(item[props.svalue]);if (arrIndex > -1) {// 如果该选项已经选中,当点击后就不选中changevalue.splice(arrIndex, 1);realValue.splice(arrIndex, 1);} else {// 否则选中该选项changevalue.push(item);realValue.push(item[props.svalue]);}}// 触发回调函数emit("change", changevalue, realValue);
};
</script><style lang="scss" scoped>
.uni-select-dc {position: relative;z-index: 999;.uni-select-mask {width: 100%;height: 100%;}/* 删除按钮样式*/.close-icon {height: 100%;width: 20px;display: flex;align-items: center;justify-content: center;// z-index: 3;cursor: pointer;text {position: relative;background: #c0c4cc;width: 13px;height: 13px;border-radius: 50%;border: 1px solid #bbb;&::before,&::after {content: "";position: absolute;left: 20%;top: 50%;height: 1px;width: 60%;transform: rotate(45deg);background-color: #909399;}&::after {transform: rotate(-45deg);}}}//所有情空的定位.close-postion {position: absolute;right: 35px;top: 0;height: 100%;width: 15px;}/* 多选盒子 */.uni-select-multiple {display: flex;flex-wrap: nowrap;overflow: scroll;.single-text {color: #333;}.uni-select-multiple-item {background: #f4f4f5;margin-right: 5px;padding: 2px 4px;border-radius: 4px;color: #909399;display: flex;flex-shrink: 0;}}// select部分.uni-select-dc-select {user-select: none;position: relative;z-index: 3;height: 30px;padding: 0 30px 0 10px;box-sizing: border-box;border-radius: 4px;border: 1px solid rgb(229, 229, 229);display: flex;align-items: center;font-size: 12px;color: #999;min-width: 10px;.uni-disabled {position: absolute;left: 0;width: 100%;height: 100%;z-index: 19;cursor: no-drop;background: rgba(255, 255, 255, 0.5);}.uni-select-dc-input {font-size: 14px;color: #999;display: block;width: 96%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;line-height: 30px;box-sizing: border-box;&.active {color: #333;}}.uni-select-dc-icon {cursor: pointer;position: absolute;right: 0;top: 0;height: 100%;width: 20px;display: flex;align-items: center;justify-content: center;border-left: 1px solid rgb(229, 229, 229);text {display: block;width: 0;height: 0;border-width: 12rpx 12rpx 0;border-style: solid;border-color: #bbb transparent transparent;transition: 0.3s;}&.disabled {cursor: no-drop;text {width: 20rpx;height: 20rpx;border: 2px solid #ff0000;border-radius: 50%;transition: 0.3s;position: relative;z-index: 999;&::after {content: "";position: absolute;top: 50%;left: 0;width: 100%;height: 2px;margin-top: -1px;background-color: #ff0000;transform: rotate(45deg);}}}}.uni-select-dc-inner {cursor: pointer;position: absolute;right: 0;top: 0;height: 100%;width: 20px;display: flex;align-items: center;justify-content: center;text {display: block;width: 10px;height: 10px;position: absolute;right: 10px;top: 6px;border: 1px solid #bbb;transform: rotate(-45deg);border-color: transparent transparent#bbb #bbb;transition: 0.3s;}&.disabled {cursor: no-drop;text {width: 20rpx;height: 20rpx;border: 2px solid #ff0000;border-radius: 50%;transition: 0.3s;position: relative;z-index: 999;&::after {content: "";position: absolute;top: 50%;left: 0;width: 100%;height: 2px;margin-top: -1px;background-color: #ff0000;transform: rotate(45deg);}}}}// 激活之后,图标旋转180度&.active .uni-select-dc-icon {text {transform: rotate(180deg);}}&.active .uni-select-dc-inner {text {position: absolute;right: 10px;top: 12px;transform: rotate(-225deg);}}}// options部分.uni-select-dc-options {user-select: none;position: absolute;top: calc(100% + 5px);left: 0;width: 100%;// height: 400rpx;max-height: 400rpx;border-radius: 4px;border: 1px solid rgb(229, 229, 229);background: #fff;padding: 5px 0;box-sizing: border-box;z-index: 9;.uni-select-dc-item {padding: 0 10px;box-sizing: border-box;cursor: pointer;line-height: 2.5;transition: 0.3s;font-size: 14px;// 取消长按的背景色-webkit-tap-highlight-color: rgba(255, 255, 255, 0);-webkit-user-select: none;-moz-user-focus: none;-moz-user-select: none;&.active {color: #409eff;background-color: #f5f7fa;&:hover {color: #409eff;background-color: #f5f7fa;}}&:hover {background-color: #f5f5f5;}}}
}
</style>

父组件调用:

<template><view class="arena-main">自定义下拉选择组件:<Select :value="monIndex" downInner :options="options" @change="changeValue">        </Select></view>
</template><script setup lang="ts">
import Select from "@/components/select/index.vue"
import { reactive } from "vue";let monIndex = reactive([1]);
const changeValue = (item: any, value: any) => {console.log("父组件接收到选中的值", item, value);monIndex = value;
};const options = [{ value: 0, text: "测试1" },{ value: 1, text: "测试2" },{ value: 2, text: "测试3" },{ value: 3, text: "测试4" },{ value: 4, text: "测试5" },
];</script><style lang="scss" scoped>
.arena-main {padding: 10px;
}
</style>

使用参数说明:

monIndex:选中的值列表options:可选项列表multiple:是否为多选downInner:下拉箭头是否在选择框内showValueClear:是否显示单个删除disabled:是否禁用placeholder:占位符slabel:label标签展示某项svalue:value选中的值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/200743.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++进阶之路】第四篇:set和map

文章目录 一、关联式容器健值对二、set & multiset三、map & multimap在这里插入图片描述 四、set和map底层原理 一、关联式容器健值对 关联式容器 & 键值对 二、set & multiset set & multiset 三、map & multimap map & multimap 四、set和…

Spring Framework IoC依赖注入-按Bean类型注入

Spring Framework 作为一个领先的企业级开发框架&#xff0c;以其强大的依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;机制而闻名。DI使得开发者可以更加灵活地管理对象之间的关系&#xff0c;而不必过多关注对象的创建和组装。在Spring Framework中&am…

将kali系统放在U盘中插入电脑直接进入kali系统

首先准备一个空白的 U 盘。 Kali Linux | Penetration Testing and Ethical Hacking Linux Distribution 在 Windows 上制作 Kali 可启动 USB 驱动器 Making a Kali Bootable USB Drive on Windows | Kali Linux Documentation 1. 首先下载 .iso 镜像 Index of /kali-images…

单链表OJ题--9.环形链表

9.环形链表 141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; /* 解题思路&#xff1a; 定义快慢指针fast,slow, 如果链表确实有环&#xff0c;fast指针一定会在环内追上slow指针。 */typedef struct ListNode Node; bool hasCycle(struct ListNode *head) {Node* slow …

设计模式—结构型模式之享元模式

设计模式—结构型模式之享元模式 享元模式(Flyweight Pattern)&#xff0c;运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象&#xff0c;而这些对象都很相似&#xff0c;状态变化很小&#xff0c;可以实现对象的多次复用。对象结构型。 在享元模式中可以共…

Arduino库之U8g2lib

某些图片、表格在手机竖屏状态下会显示不全&#xff0c;横屏显示即可。最好是用平板或电脑看。大部分内容摘自官网。 简介 U8g2 U8glib是用于单色显示屏的图形库&#xff0c;它可以用于51、Arduino、ARM控制显示屏&#xff0c;目前作者olikraus已经更新到version2了&#xff0…

瑞格心理咨询系统设置多个管理员的操作方法

使用瑞格心理咨询系统&#xff0c;需要设置多个admin权限的管理员账号来管理&#xff0c;咨询厂家答复只能有1个管理员&#xff0c;个人觉得不可能&#xff0c;于是开始折腾。 解决办法&#xff1a; 在没有数据字典的情况下&#xff0c; 通过遍历数据库&#xff0c;发现用户信…

16. @PostConstruct注解和开关原理(验证码开关、IP开关)

1►PostConstruct注解 PostConstruct是java自带的注解&#xff0c;会在java项目启动的时候先执行下面的方法 2►开关原理&#xff08;验证码开关&#xff09; 我们的项目具有验证码功能&#xff0c;旧版不支持关闭&#xff0c;新版已经支持关闭了。 我们打开页面“参数管…

使用 ClickHouse 做日志分析

原作&#xff1a;Monika Singh & Pradeep Chhetri 这是我们在 Monitorama 2022 上发表的演讲的改编稿。您可以在此处找到包含演讲者笔记的幻灯片和此处的视频。 当 Cloudflare 的请求抛出错误时&#xff0c;信息会记录在我们的 requests_error 管道中。错误日志用于帮助解…

Nginx - 本机读取服务器图像、视频

目录 一.引言 二.安装 Nginx 1.安装 By apt 2.安装 By 官网 三.配置 Nginx 1.Linux 机器配置 2.重启 Nginx 服务 3.本机查看机器文件 四.总结 一.引言 前面介绍了 GFP-GAN、PNG2GIF、GIF2PNG 等操作&#xff0c;我们生成的 video、gif、png 等形式的文件都存储在 lin…

【FPGA】Verilog:升降计数器 | 波纹计数器 | 约翰逊计数器 | 实现 4-bit 升降计数器的 UP/DOWN

目录 Ⅰ. 理论部分 0x00 升降计数器&#xff08;UP DOWN Counter&#xff09; 0x01 波纹计数器&#xff08;Ripple Counter&#xff09; 0x02 约翰逊计数器&#xff08;Johnson Counter&#xff09; Ⅱ. 实践部分 0x00 实现&#xff1a;升降计数器&#xff08;4-bit&…

Unity - 实现模型动态伸长缩短,贴图不变形(材质球参数篇)

思路为修改模型材质球的Tiling参数&#xff0c;根据与自身localScale的值得到合适的比例&#xff0c;再修改Tiling值 var mat target.transform.GetComponent<Renderer>().material; var oriValue mat.mainTextureScale;//沿着Y轴伸缩 oriValue.y 1 * target.transfo…

使用DHorse发布SpringBoot项目到K8S

前言 在介绍DHorse的操作之前&#xff0c;先来介绍一下使用k8s发布应用的步骤&#xff0c;以SpringBoot应用为例进行说明。 1.首先从代码仓库下载代码&#xff0c;比如GitLab&#xff1b; 2.接着进行构建&#xff0c;比如使用Maven&#xff1b; 3.如果要使用k8s作为编排&am…

MySQL - 4种基本索引、聚簇索引和非聚索引、索引失效情况

目录 一、索引 1.1、简单介绍 1.2、索引的分类 1.2.1、主键索引 1.2.2、单值索引&#xff08;单列索引、普通索引&#xff09; 1.2.3、唯一索引 1.2.4、复合索引 1.2.5、复合索引经典问题 1.3、索引原理 1.3.1、主键自动排序 1.3.2、索引的底层原理 1.3.3、B 树和 B…

海康威视监控相机的SDK与opencv调用(非工业相机)

1.研究内容 本篇主要对海康威视的监控相机的SDK回调进行研究&#xff0c;并于opencv结合&#xff0c;保存图像,以供后续其他处理&#xff0c;开发语言为C 2.步骤及方法 2.1 海康SDK介绍 海康SDK下载地址 根据自身编译环境&#xff0c;下载对应的SDK&#xff0c;需要注意的是…

wincc定时器功能介绍

1定时器功能介绍 WinCC中定时器的使用可以使WinCC按照指定的周期或者时间点去执行任务&#xff0c;比如周期执行变量归档、在指定的时间点执行全局脚本或条件满足时打印报表。WinCC已经提供了一些简单的定时器&#xff0c;可以满足大部分定时功能。但是在有些情况下&#xff0c…

SpringBoot:ch02 配置文件(日志)

前言 简单介绍 Spring Boot 中常见的配置文件类型&#xff0c;如 application.properties 和 application.yml 等&#xff0c;并说明它们各自的特点和用途。 一、前期准备 1、新建项目&#xff0c;结构如下 2、添加依赖 <?xml version"1.0" encoding"UTF…

OpenLayers入门,OpenLayers6的WebGLPointsLayer图层样式运算符详解

专栏目录: OpenLayers入门教程汇总目录 前言 本章讲解使用OpenLayers6的WebGL图层显示大量点情况下,列举出所有WebGLPointsLayer图层所支持的所有样式运算符大全。 二、基于的OpenLayers版本 "ol": "^6.15.1"使用npm安装依赖npm install ol@6.15.1使…

html页面直接使用elementui Plus时间线 + vue3

直接上效果图 案例源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"../js/vue3.3.8/vue.global.js"></script><link rel"styles…

英语六级范文模板

目录 现象解释 观点选择 问题解决 六级只考议论文&#xff0c;我们将从现象解释&#xff0c;观点选择&#xff0c;问题解决三个角度给出范文&#xff1a; 多次使用的句子&#xff0c;就可以作为模板记下来~~ 现象解释 In the contemporary world, the ability to meet cha…