nut-popup 二次封装 弹窗 选择组件 vue3

2023-11-30 18:01

本文主要是介绍nut-popup 二次封装 弹窗 选择组件 vue3,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

<template><nut-popup overlay-class="diolagClass" pop-class="nut-popup-name-class" :position="posititon"v-model:visible="showBasic" @click-overlay="handleClickoverlay" duration="0.2"><div class="search-container" v-show="isSearch"><div class="search-ipt"><input type="text" v-model="cityValue" /><IconFont name="search" color="#cccccc" style="position: absolute;left: 10px;top: 50%;transform: translateY(-50%);"></IconFont></div><div class="search-Icon"><IconFont name="search" color="#ffffff" style="font-size: 16px"></IconFont></div></div><scroll-view :scroll-y="true" :style="{ 'min-height': `${listContainerHeight / 2}px` }"><div class="list-container" v-if="!status"><div class="item" @click="toggleAllItems" :class="{ selected: areAllOptionsSelected() }">全部</div><div class="item" v-for="(item, index) in state.options1" :key="item.id" @click="toggleItem(item)":class="{ selected: isSelected(item.name) }">{{ item.name }}</div></div><div class="list-container" v-else><div class="item" v-for="(item, index) in state.options1" :key="item.id" @click="toggleRadioItem(item)":class="{ selected: isSelected(item.name) }">{{ item.name }}</div></div></scroll-view><div class="footerBtn" v-if="!status"><div class="footerBtn-left">已选择<span style="color: #ee0a24">{{ selectedItems.length }}</span>个</div><div class="footerBtn-right"><nut-button plain type="primary" @click="resetSelected"><template #icon><IconFont name="del2"></IconFont></template>重置</nut-button><nut-button style="margin-left: 20px" color="linear-gradient(to right, #ff6034, #ee0a24)"@click="handleClickConfirm" type="info">确认选择</nut-button></div></div><div v-else style="height: 40px"></div></nut-popup>
</template>
<script setup>
import { reactive, ref } from "vue";
import { storeToRefs } from "pinia";
import { IconFont } from "@nutui/icons-vue-taro";
import { toRefs } from "vue";
import Taro from "@tarojs/taro";
const props = defineProps({list: Array,status: Boolean,listContainerHeight: Number,showBasic: Boolean,type: String,posititon: String,isSearch: Boolean
});
const { list, status, listContainerHeight, showBasic, type, posititon, isSearch } =toRefs(props);
const selectedItems = ref([]);//判断一下当前的组件是哪个数据触发的
if (type.value == "movie" && Taro.getStorageSync("movie").length) {selectedItems.value = Taro.getStorageSync("movie");} else if (type.value == "cinema" && Taro.getStorageSync("cinema").length) {selectedItems.value = Taro.getStorageSync("cinema");} else {selectedItems.value = [];}const emit = defineEmits(["onFlagChange", "onconfirmItems", "seatChange", "onupdatedItems"])
const sleectedCloneItems = ref([]);const state = reactive({options1: list,
});const isSelected = (id) => {// console.log(id,"valSeat");return selectedItems.value.includes(id);
};const toggleItem = (e) => {if (isSelected(e.name)) {selectedItems.value = selectedItems.value.filter((item) => item !== e.name);} else {selectedItems.value.push(e.name);}
};
// 新增函数来检查是否所有选项都被选中
const areAllOptionsSelected = () => {return state.options1.every((item) => isSelected(item.name));
};// 修改点击"全部"选项的逻辑
const toggleAllItems = () => {if (areAllOptionsSelected()) {selectedItems.value = [];} else {selectedItems.value = state.options1.map((item) => item.name);}
};const toggleRadioItem = (e) => {selectedItems.value = [e.name];emit("seatChange", selectedItems.value);
};
const handleClickoverlay = () => {emit("onFlagChange", false);}//点击确定
const handleClickConfirm = async () => {console.log(selectedItems);await emit("onconfirmItems", { result: selectedItems.value, type: type.value })await emit("onFlagChange", false);}
//重置按钮const resetSelected = () => {if (!selectedItems.value.length) {return}selectedItems.value = [];
}</script>
<style lang="less">
.diolagClass {top: 65px !important;
}.nut-popup-name-class {margin-top: 65px;padding-top: 20px;
}.nut-popup--top {width: 100% !important;border-bottom-left-radius: 40px;border-bottom-right-radius: 40px;
}.list-container {display: flex;// align-items: center;justify-content: space-around;flex-wrap: wrap;padding: 0 20px;.selected {color: #ee0a24 !important;border: 1px solid #ee0a24;background-color: #fff !important;}.item {margin-top: 10px;font-size: 24px;width: 160px;height: 60px;line-height: 60px;background-color: #f7f8fb;border-radius: 25px;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;text-overflow: ellipsis;overflow: hidden;color: #15181d;text-align: center;}
}.footerBtn {display: flex;justify-content: space-between;align-items: center;padding: 20px;.footerBtn-left {color: #858a99;font-size: 30px;}.footerBtn-right {}
}.search-container {display: flex;justify-content: space-between;padding: 20px 40px;align-items: center;.search-ipt {background-color: #fff;border: 1px solid #ccc;// flex: 4;flex: 1;position: relative;border-radius: 45px;padding: 20px;font-size: 25px;input {padding-left: 70px;color: #858a99;}}.search-Icon {background-color: #fff;width: 50px;height: 50px;line-height: 50px;border-radius: 50%;display: flex;justify-content: center;align-items: center;margin-left: 40px;background-color: #ee0a24;opacity: 0.6;padding: 10px;}
}
</style>

1.目前组件需求 

移动端使用 ,当需要时选择 单选或者多选的时候 都可以用这个组件

2.效果图片

3.样式大家还可以微调 

这篇关于nut-popup 二次封装 弹窗 选择组件 vue3的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/437997

相关文章

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

SpringQuartz定时任务核心组件JobDetail与Trigger配置

《SpringQuartz定时任务核心组件JobDetail与Trigger配置》Spring框架与Quartz调度器的集成提供了强大而灵活的定时任务解决方案,本文主要介绍了SpringQuartz定... 目录引言一、Spring Quartz基础架构1.1 核心组件概述1.2 Spring集成优势二、J

鸿蒙中Axios数据请求的封装和配置方法

《鸿蒙中Axios数据请求的封装和配置方法》:本文主要介绍鸿蒙中Axios数据请求的封装和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.配置权限 应用级权限和系统级权限2.配置网络请求的代码3.下载在Entry中 下载AxIOS4.封装Htt

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

CSS will-change 属性示例详解

《CSSwill-change属性示例详解》will-change是一个CSS属性,用于告诉浏览器某个元素在未来可能会发生哪些变化,本文给大家介绍CSSwill-change属性详解,感... will-change 是一个 css 属性,用于告诉浏览器某个元素在未来可能会发生哪些变化。这可以帮助浏览器优化