UNIAPP popper气泡弹层【unibest框架下】vue3+typescript
看了下市场的代码,要么写的不怎么好,要么过于复杂。于是把市场的代码下下来了自己改。200行代码撸了个弹出层组件。兼容H5和APP。
功能:
1)只支持上下左右4个方向的弹层不支持侧边靠齐
2)不对屏幕边界适配
3)支持弹层外边点击自动隐藏
4)支持3种内容模式:
1. 弹出提示文本
2. slot内容占位
3. 支持菜单模式
BWT:弹层外点击自动隐藏基于unibest框架的页面模板技术,这里就不放代码了,自己想想怎么弄😏 。提示:使用事件总线模式,放出的代码也提示了部分用法。
效果,H5下:

APP下:

小程序下:

组件代码:
<!--自定义弹出层/菜单组件1)只支持上下左右4个方向的弹层不支持侧边靠齐2)不对屏幕边界适配3)支持弹层外边点击自动隐藏4)支持3种内容模式:1. 文本为内容2. slot内容占位3. 菜单模式@Author Jim 24/10/08-->
<template><view><view class="cc_popper" @click.stop="handleClick"><slot></slot><viewclass="cc_popper_layer border-2rpx border-solid"@click.stop="() => {}":style="[data.layerStyle,{visibility: data.isShow ? 'visible' : 'hidden',opacity: data.isShow ? 1 : 0,color: props.textColor,backgroundColor: props.bgColor,borderColor: 'var(--cc-box-border)'}]"><view class="px-20rpx py-10rpx" v-if="content.length > 0 || $slots.content"><!-- 内容模式 --><slot name="content">{{ content }}</slot></view><view v-else class="py-5rpx px-10rpx"><template v-for="(conf, index) in props.menu" :key="index"><view v-if="index > 0" class="bg-box-border opacity-70 h-2rpx w-full" /><viewclass="px-20rpx py-10rpx menu-item my-5rpx"@click="() => {conf.callback()data.isShow = false}">{{ conf.title }}</view></template></view><view:class="['w-0', 'h-0', 'z-9', 'absolute', 'popper-arrow-on-' + props.direction]":style="[data.arrowStyle]"/></view></view></view>
</template>
<script lang="ts" setup>
import { CSSProperties } from 'vue'
import * as utils from '@/utils'
let instanceconst { screenWidth } = uni.getSystemInfoSync()const pixelUnit = screenWidth / 750 // rpx->px比例基数export interface MenuConf {icon?: string // 指示图标title: string // 菜单文本callback: () => void // 点击事件
}const props = withDefaults(defineProps<{textColor?: string // 指定内部文本颜色bgColor?: stringborderColor?: stringcontent?: string // 可以指定文本content,或者指定 slot content来显示弹窗内容menu?: Array<MenuConf> // 下拉菜单模式direction?: 'top' | 'bottom' | 'left' | 'right' // 弹层位置alwaysShow: boolean}>(),{textColor: 'var(--cc-txt)',bgColor: 'var(--cc-box-fill)', // 默认弹框色borderColor: 'var(--cc-box-border)', // 默认弹框边框色content: '',menu: () => [],direction: 'top',alwaysShow: false}
)const data = reactive<{isShow: booleanlayerStyle: CSSProperties // CSS定义一层够了arrowStyle: CSSProperties
}>({isShow: false,layerStyle: {},arrowStyle: {}
})onMounted(() => {instance = getCurrentInstance()if (props.alwaysShow) {nextTick(() => handleClick())}
})onUnmounted(() => {if (!props.alwaysShow) {utils.off(utils.Global.CC_GLOBAL_CLICK, hideLayer) // 移除全局点击监听}
})const hideLayer = (event: MouseEvent) => {data.isShow = falseutils.off(utils.Global.CC_GLOBAL_CLICK, hideLayer)
}const handleClick = async () => {if (data.isShow) {if (props.alwaysShow) {return}utils.off(utils.Global.CC_GLOBAL_CLICK, hideLayer)return (data.isShow = false)}const rects: UniApp.NodeInfo[] = await utils.getRectAll('.cc_popper,.cc_popper_layer', instance)const srcRect: UniApp.NodeInfo = rects[0]const layerRect: UniApp.NodeInfo = rects[1]data.arrowStyle['border' + props.direction.charAt(0).toUpperCase() + props.direction.slice(1)] ='10rpx solid var(--cc-box-border)'switch (props.direction) {case 'top': {data.layerStyle.left = `${(srcRect.width - layerRect.width) / 2}px`data.layerStyle.bottom = `${srcRect.height + 16 * pixelUnit}px`data.arrowStyle.left = `${layerRect.width / 2 - 12 * pixelUnit}px`console.log(data.arrowStyle.left)break}case 'bottom': {data.layerStyle.left = `${(srcRect.width - layerRect.width) / 2}px`data.layerStyle.top = `${srcRect.height + 16 * pixelUnit}px`data.arrowStyle.left = `${layerRect.width / 2 - 12 * pixelUnit}px`break}case 'left': {data.layerStyle.right = `${srcRect.width + 16 * pixelUnit}px`data.layerStyle.top = `${(srcRect.height - layerRect.height) / 2}px`data.arrowStyle.top = `${layerRect.height / 2 - 12 * pixelUnit}px`break}case 'right': {data.layerStyle.left = `${srcRect.width + 16 * pixelUnit}px`data.layerStyle.top = `${(srcRect.height - layerRect.height) / 2}px`data.arrowStyle.top = `${layerRect.height / 2 - 12 * pixelUnit}px`break}}data.isShow = trueif (!props.alwaysShow) {utils.on(utils.Global.CC_GLOBAL_CLICK, hideLayer)}
}
</script>
<style lang="scss" scoped>
$arrow-size: 12rpx;
$arrow-offset: -12rpx;.cc_popper {position: relative;display: inline-block;
}.cc_popper_layer {position: absolute;display: inline-block;white-space: nowrap;border-radius: 10rpx;transition: opacity 0.3s ease-in-out;
}.popper-arrow-on-top {bottom: $arrow-offset;border-right: $arrow-size solid transparent;border-left: $arrow-size solid transparent;
}.popper-arrow-on-right {left: $arrow-offset;border-top: $arrow-size solid transparent;border-bottom: $arrow-size solid transparent;
}.popper-arrow-on-left {right: $arrow-offset;border-top: $arrow-size solid transparent;border-bottom: $arrow-size solid transparent;
}.popper-arrow-on-bottom {top: $arrow-offset;border-right: $arrow-size solid transparent;border-left: $arrow-size solid transparent;
}.menu-item {&:active {background-color: #88888840;}
}
</style>
测试页面:
<template><view class="text-txt w-full h-full"><view>消息</view><view class="x-items-between px-200rpx pt-100rpx"><cc-popper direction="left" content="说啥好呢" alwaysShow><view class="w-100rpx"><u-button text="左边" /></view></cc-popper><view class="w-100rpx"><cc-popper direction="top" content="向上看" alwaysShow><view class="w-100rpx"><u-button text="上面" /></view></cc-popper><cc-popper direction="bottom" content="下边也没有" alwaysShow><view class="w-100rpx mt-20rpx"><u-button text="下面" /></view></cc-popper></view><cc-popper direction="right" content="右边找找" alwaysShow><view class="w-100rpx"><u-button text="右边" /></view></cc-popper></view><view class="x-items-between px-150rpx pt-400rpx"><cc-popper alwaysShow><view class="w-200rpx"><u-button shape="circle" text="烎" /></view><template #content><text class="text-100rpx">🤩</text></template></cc-popper><cc-popper alwaysShow :menu="data.menu"><div class="w-100rpx h-100rpx bg-red"></div></cc-popper></view></view>
</template>
<script lang="ts" setup>
import { MenuConf } from '@/components/ccframe/cc-popper.vue'const data = reactive<{menu: Array<MenuConf>
}>({menu: [{title: '口袋1',callback: () => {console.log('糖果')}},{title: '口袋2',callback: () => {console.log('退出系统')}},{title: '口袋3',callback: () => {console.log('空的')}}]
})
</script>
对了,菜单的图标支持还没写。等用到的时候再加上去,代码放这存档,后面再更新:)
相关文章:
UNIAPP popper气泡弹层【unibest框架下】vue3+typescript
看了下市场的代码,要么写的不怎么好,要么过于复杂。于是把市场的代码下下来了自己改。200行代码撸了个弹出层组件。兼容H5和APP。 功能: 1)只支持上下左右4个方向的弹层不支持侧边靠齐 2)不对屏幕边界适配 3)支持弹层外边点击自动隐藏 4)支持…...
launcher.py: error: the following arguments are required: --output_dir
记录一个LLaMA-Factroy配置过程。 安装 git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e ".[torch,metrics]"训练 CUDA_VISIBLE_DEVICES0 llamafactory-cli train example/train_lora/.yaml按理说配置好文件应…...
C语言基础之结构体
今天我们来讲讲C语言基础的最后一个知识点了 —— 结构体。不知道大家对前面的C语言基础的知识点掌握的怎么样了呢?下面我们就开始讲解结构体的相关知识点吧! 什么是结构体呢?或者说结构体有什么作用呢?对于复杂对象来说ÿ…...
Redis入门第四步:Redis发布与订阅
欢迎继续跟随《Redis新手指南:从入门到精通》专栏的步伐!在本文中,我们将深入探讨Redis的发布与订阅(Pub/Sub)模式。这是一种强大的消息传递机制,适用于各种实时通信场景,如聊天应用、实时通知和…...
MySQL 之权限与授权
MySQL 权限及授权系统用于控制数据库用户对数据库资源的访问和操作权限。它提供了一种细粒度的安全控制机制,确保只有被授权的用户才能执行特定的操作。MySQL 的权限控制体系非常灵活,支持多种权限类型及级别(数据库、表、列、存储过程等&…...
解决方案:Pandas里面的loc跟iloc,有什么区别
文章目录 一、现象二、解决方案案例使用loc使用iloc 简单总结 一、现象 在用Pandas库处理数据的时候,久而久之不用loc跟iloc,难免会有些混乱记混 二、解决方案 在Pandas中,loc和iloc是两种常用的数据选择方法,它们的主要区别在…...
C# 和 C++ 混合编程
以下是一个关于 C# 和 C 混合编程 的教程详细目录,涵盖了混合编程中的各个重要方面: 目录 1. 引言 1.1 什么是混合编程? 1.2 为什么选择 C# 和 C 进行混合编程? 1.3 应用场景和优势 2. 基本概念 2.1 C# 和 C 的基础差异 2.…...
Vxe UI vue vxe-table 实现表格单元格选中功能
Vxe UI vue vxe-table 实现表格单元格选中功能 在表格中实现鼠标点击任意单元格,选取的功能,通过 mouse-config 配置就可以开启单选功能,多选单元格选取功能需安装插件支持。 代码 参数说明 mouse-config 鼠标配置项: selected&…...
组合模式详解
1、组合模式基本介绍 1) 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以 表示“整体-部分”的层次关系。 2) 组合模式依据树形结构来组合对象,用来表示部…...
AltiumDesigner脚本开发-DIP封装制作
1.点击工具栏的运行工具(蓝色向右三角图标)可以执行脚本程序; 2.点击菜单栏Run->Run可以执行脚本程序; 3.在脚本编辑器中,按键盘的F9键可以执行脚本程序; 4.通过菜单栏执行脚本程序(需要将程序添加到菜单栏中&am…...
乌班图基础设施安装之Mysql8.0+Redis6.X安装
简介:云服务器基础设施安装之 Mysql8.0Redis6.X 安装 Docker安装 # 按照依赖 yum install -y yum-utils device-mapper-persistent data lvm2 Docker Mirror 从去年开始. hub.docker.com[1] 在国内的访问速度极慢. 当时大家主要还是依赖国内的一些镜像源: 如中科…...
【动态规划-最长递增子序列(LIS)】力扣673.最长递增子序列的个数
给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。 注意 这个数列必须是 严格 递增的。 示例 1: 输入: [1,3,5,4,7] 输出: 2 解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。 示例 2: 输入: [2,2,2,2,2] 输出: 5 解释:…...
SQL优化 where谓词条件is null优化
1.创建测试表及谓词条件中包含is null模拟语句 create table t641 as select * from dba_objects; set autot trace select SUBOBJECT_NAME,OBJECT_NAME from t641 where OBJECT_NAMEWRI$_OPTSTAT_SYNOPSIS$ and SUBOBJECT_NAME is null; 2.全表扫描逻辑读1237 3.创建等值谓词条…...
Starrocks 元数据恢复 failed to load journal type 10242
fe 启动异常 2024-10-08 09:24:57.66908:00 INFO (stateChangeExecutor|87) [DatabaseTransactionMgr.replayUpsertTransactionState():1702] remove expired transaction: TransactionState. txn_id: 189324, label: delete_031c5090-7e2d-11ef-bdd8-000c29967e13, db id: 100…...
《深度学习》神经语言模型 Word2vec CBOW项目解析、npy/npz文件解析
目录 一、关于word2vec 1、什么是word2vec 2、常用训练算法 1)CBOW 2)SkipGram 二、关于npy、npz文件 1、npy文件 1)定义 2)特性 3)用途 4)保存及读取 运行结果: 运行结果…...
黄粱一梦,镜花水月总是空
总有人间一两风,埋我十万八千梦 自古以来,梦在我们的生活中一直是一个神秘玄幻而又发人深省的存在,我们一生中有三分之一的时间都在睡觉,做过的梦也是丰富多彩数不胜数。 而从科学的角度来说,梦是我们潜意识里的生活…...
【分布式事务-01】分布式事务之2pc两阶段提交
redis系列整体栏目 内容链接地址【一】分布式事务之2pc两阶段提交https://zhenghuisheng.blog.csdn.net/article/details/142406325 分布式事务之2pc两阶段提交 一,分布式事务之2pc两阶段提交1,两阶段提交(2pc)2,2pc两阶段提交实现思路3&…...
docker 安装 rabbitMQ
第一步:准备工作 # 打开docker目录 [rootMuYu ~]# cd /usr/local/docker/ # 创建rabbitmq文件夹 [rootMuYu docker]# mkdir rabbitmq # 打开rabbitmq文件夹 [rootMuYu docker]# cd rabbitmq/ # 创建挂载目录 [rootMuYu rabbitmq]# mkdir data 第二步ÿ…...
知识改变命运 数据结构【java对象的比较】
0:前言 在基本数据类型中,我们可以直接使用号比较是否相等,还记的学堆哪里时候,插入一个数据,就会与其他数据进行比较,当时我们传入的是Integer类型,在Integer类里面已经实现了compare。 如果…...
01_23 种设计模式之《简单工厂模式》
文章目录 一、什么是设计模式二、设计模式类型简单工厂模式及应用场景定义抽象产品类和具体产品类实现工厂类客户端代码注意事项 一、什么是设计模式 设计模式:在软件研发过程中,经过实战验证,用于解决在特定环境下、重复出现的,…...
如何为Whisper ASR Webservice开发自定义引擎和插件
如何为Whisper ASR Webservice开发自定义引擎和插件 【免费下载链接】whisper-asr-webservice OpenAI Whisper ASR Webservice API 项目地址: https://gitcode.com/gh_mirrors/wh/whisper-asr-webservice Whisper ASR Webservice是一个基于OpenAI Whisper的语音识别服务…...
基因组变异致病性预测:从SIFT、PolyPhen到PrimateAI的算法演进
点击 “AladdinEdu,你的AI学习实践工作坊”,注册即送-H卡级别算力,沉浸式云原生集成开发环境,80G大显存多卡并行,按量弹性计费,教育用户更享超低价。 摘要:基因组变异致病性预测是精准医学的关键…...
cv_resnet101_face-detection_cvpr22papermogface保姆级教程:GPU显存占用监控与自动释放策略
cv_resnet101_face-detection_cvpr22papermogface保姆级教程:GPU显存占用监控与自动释放策略 1. 引言 如果你正在使用基于ResNet101的MogFace人脸检测模型,可能会遇到一个常见问题:GPU显存占用越来越高,最终导致程序崩溃。尤其是…...
视频高清低延时直播/音视频点播/云点播/云直播EasyDSS在校园教育/K12教育等各场景中的应用介绍
在线教育的核心竞争力,归根结底在于教学体验的优劣,而视频技术作为线上教学的核心载体,直接决定了教学体验的上限。随着在线教育行业的快速迭代,学员对线上课堂的要求愈发严苛:不仅需要高清流畅、稳定无卡顿的音视频传…...
三轴桁架机械手上下料控制系统详细说明书
三轴桁架机械手上下料用西门子smart200 S 020三轴桁架机械手上下料用西门子smart200 ST40 脉冲控制3轴伺服可上西门子触摸屏详细注释,控制系统详细说明书,文档详细讲解组态和指令,I0表,电气原理图G一、概述本说明书旨在详细介绍三…...
5分钟快速上手:UNTRUNC视频修复工具终极指南
5分钟快速上手:UNTRUNC视频修复工具终极指南 【免费下载链接】untrunc Restore a damaged (truncated) mp4, m4v, mov, 3gp video. Provided you have a similar not broken video. 项目地址: https://gitcode.com/gh_mirrors/unt/untrunc 你是否曾经因为相机…...
基于python宠物医院药品管理系统的设计与实现
目录同行可拿货,招校园代理 ,本人源头供货商功能模块设计技术实现要点扩展功能建议项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作同行可拿货,招校园代理 ,本人源头供货商 功能模块设计 药品信息管理模块 实现药品基础信息的…...
Llama-3.2V-11B-cot入门必看:Streamlit会话状态管理保障多用户隔离
Llama-3.2V-11B-cot入门必看:Streamlit会话状态管理保障多用户隔离 1. 项目概述 Llama-3.2V-11B-cot是基于Meta Llama-3.2V-11B-cot多模态大模型开发的高性能视觉推理工具,专为双卡4090环境深度优化。该工具通过Streamlit框架构建了宽屏友好的交互界面…...
QuickBMS技术探索者指南:游戏资源解析与逆向工程实战
QuickBMS技术探索者指南:游戏资源解析与逆向工程实战 【免费下载链接】QuickBMS QuickBMS by aluigi - Github Mirror 项目地址: https://gitcode.com/gh_mirrors/qui/QuickBMS 在数字内容创作与逆向工程领域,文件格式的多样性与加密机制的复杂性…...
利用快马AI快速原型化一个Python Socket聊天室应用
最近在学习计算机网络相关的知识,发现Socket编程是个很有意思的实践方向。正好在InsCode(快马)平台上尝试用AI快速原型化了一个Python Socket聊天室应用,整个过程比想象中顺利很多,分享下我的实现思路和体验。 项目背景与需求分析 这个聊天…...
