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.mzph.cn/news/157840.shtml

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

相关文章

31、Flink的SQL Gateway介绍及示例

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

梳理一名Go后端程序员日常用的软件~

大家好&#xff0c;我是豆小匠。 这期分享下我日常工作用到的软件和工具&#xff01; 省流版图片↓↓↓ 工具分为四类&#xff1a;编码软件、笔记/文档软件、开发工具和日常软件等。 1. 编码软件 1.1. Goland 出自JetBrain家族&#xff0c;IDE的王者&#xff0c;作为我的…

Vuetify:定制化、响应式的 Vue UI 库 | 开源日报 No.83

vuetifyjs/vuetify Stars: 38.1k License: MIT Vuetify 是一个无需设计技能的 UI 库&#xff0c;具有精美手工制作的 Vue 组件。它具有以下核心优势和主要功能&#xff1a; 可定制性&#xff1a;使用 SASS/SCSS 进行广泛自定义&#xff0c;并提供默认配置和蓝图。响应式布局&…

debian10 开启rdp安装firefox并解决firefox 中文乱码

debian10 开启rdp安装firefox apt -y install tigervnc-standalone-server apt -y install xrdp tigervnc-standalone-server systemctl enable xrdp --nowapt install firefox-esrmstsc连接 firefox-settings-general-fonts-advanced-Simplified Chinese

如何看待Unity新收费模式?

Unity新收费模式的变化主要在于将收费重心从功能分级收费转变为资源使用量收费&#xff0c;这个改变已经引起了一定的争议和反响。以下是我个人的看法&#xff1a; 优点&#xff1a; 更公平的收费方式&#xff1a;新的收费模式将更加公平&#xff0c;用户只需按照实际使用的数…

汇编-PUSHFD和POPFD标志寄存器值压栈和出栈

PUSHFD指令将32位EFLAGS寄存器内容压入堆栈&#xff0c; 而POPFD指令则将栈顶单元内容弹出到EFLAGS寄存器 格式&#xff1a;

接口自动化测试:pytest基础讲解

为什么要做接⼝测试&#xff1f; 只靠前端测试很难确保很⾼的覆盖率。接⼝测试&#xff0c;可以模拟出各种类型的⼊参&#xff0c;包括⼀些在前端模拟不出来的⼊参&#xff0c;还能根据接⼝⽂档的定义&#xff0c;设计出相对完善的⼊参值&#xff0c;在接⼝层保证质量&#xf…

常见树种(贵州省):006栎类

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、麻栎 …

基础课10——自然语言生成

自然语言生成是让计算机自动或半自动地生成自然语言的文本。这个领域涉及到自然语言处理、语言学、计算机科学等多个领域的知识。 1.简介 自然语言生成系统可以分为基于规则的方法和基于统计的方法两大类。基于规则的方法主要依靠专家知识库和语言学规则来生成文本&#xff0…

svn文件不显示红色感叹号

如下图所示&#xff0c;受svn版本控制的文件不显示下图中红色感叹号和绿色对号时&#xff0c; 可以试着如下操作 空白处单击右键&#xff0c;具体操作如下图

Rust可空类型Option

文章目录 Option基础模式匹配unwrap Rust基础教程&#xff1a;初步⚙所有权⚙结构体和枚举类⚙函数进阶⚙泛型和特征⚙并发和线程通信⚙cargo包管理 Rust进阶教程&#xff1a;用宏实现参数可变的函数⚙类函数宏 Option基础 在一些编程语言中&#xff0c;允许存在空值&#xf…

docker的基本使用以及使用Docker 运行D435i

1.一些基本的指令 1.1 容器 要查看正在运行的容器&#xff1a; sudo docker ps 查看所有的容器&#xff08;包括停止状态的容器&#xff09; sudo docker ps -a 重新命名容器 sudo docker rename <old_name> <new_name> <old_name> 替换为你的容器名称…

用 HLS 实现 UART

用 HLS 实现 UART 介绍 UART 是一种旧的串行通信机制&#xff0c;但仍在很多平台中使用。它在 HDL 语言中的实现并不棘手&#xff0c;可以被视为本科生的作业。在这里&#xff0c;我将通过这个例子来展示在 HLS 中实现它是多么容易和有趣。 因此&#xff0c;从概念上讲&#xf…

配置你的VsCode服务器,随时随地写代码!

Hello&#xff0c;大家好&#xff0c;好久不见&#xff01;前段时间忙着秋招和论文&#xff0c;临近秋招结束&#xff0c;终于有时间更新了 前段时间实验室搞一个4090服务器&#xff0c;终于可以无所忌惮地跑深度学习咯&#xff0c;刚好要配置环境&#xff0c;今天就教大家通…

Unity收费对谁影响最大

Unity的收费政策对以下几类人群影响最大&#xff1a; 游戏开发商&#xff1a;Unity收费政策中最直接的影响对象就是游戏开发商。对于那些使用Unity引擎制作游戏的开发商来说&#xff0c;他们将需要考虑新的许可证费用和服务费用&#xff0c;这可能会对他们的盈利和发展产生影响…

Linux MYSQL-5.7.23-rpm安装(附带安装包)

系统环境 OS 版本(Linux) CentOS-7-x86_64-Minimal-1511Java版本 jdk1.7及以上 卸载系统自带mariadb-lib rpm -qa|grep mariadbrpm -e mariadb-libs-5.5.68-1.el7.x86_64 --nodeps解压tar包 tar -xvf mysql*.tar以下加粗rpm包需要安装&#xff1a; mysql-community-common…

基于SSM的学院网站设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

AVR单片机在机器人视觉导航中的应用研究

AVR单片机在机器人视觉导航中的应用是一项前沿的研究领域&#xff0c;旨在实现机器人在未知环境中的自主导航和避障功能。本文将介绍AVR单片机在机器人视觉导航中的应用原理和实现步骤&#xff0c;并提供相应的代码示例。 1. 导航概述 机器人视觉导航是基于计算机视觉和控制理…

SpringBoot 整合 JdbcTemplate(配置多数据源)

数据持久化有几个常见的方案&#xff0c;有 Spring 自带的 JdbcTemplate 、有 MyBatis&#xff0c;还有 JPA&#xff0c;在这些方案中&#xff0c;最简单的就是 Spring 自带的 JdbcTemplate 了&#xff0c;这个东西虽然没有 MyBatis 那么方便&#xff0c;但是比起最开始的 Jdbc…

文本分析:NLP 魔法!

一、说明 这是一个关于 NLP 和分类项目的博客。NLP 是自然语言处理&#xff0c;目前需求量很大。让我们了解如何利用 NLP。我们将通过编码来理解流程和概念。我将在本博客中介绍 BagOfWords 和 n-gram 以及朴素贝叶斯分类模型。这个博客的独特之处&#xff08;这使得它很长&…