MintUI中的mt-popup中嵌套mt-popup

常用的vue移动端组件库:官网

需求场景:弹窗上还有一层弹窗(如弹窗上的日期组件),使用MintUI中的mt-popup来实现

惯性思维,会这样写:

<mt-popup>
    <mt-popup></mt-popup>
</mt-popup>

这个是错误的,这样导致层级错误

正确写法:

<mt-popup></mt-popup>
<mt-popup></mt-popup>

还需要修改toast的堆叠层级,会被覆盖,在app.vue中修改

.mint-toast {
    z-index: 2043 !important;
}

 

<template> <list-view id="listview" style="flex: 1;background: #fff;" :refresher-enabled="false" :refresher-default-style="refresherStyle" :refresher-triggered="refresherTriggered" @scrolltolower="onScrollTolower" @scroll="scrollEvent" @touchstart="outsideTouchEvent" > <!-- 朋友圈背景图 --> <list-item class="top"> <image class="bg-image" src="/static/1.png" mode="aspectFill"></image> <view class="user-info uni-row" ref="user-info"> <text class="username">微信朋友圈</text> <image class="user-avatar" src="https://img0.baidu.com/it/u=1415523915,841919565&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1713286800&t=a9e21a0e5650a672fa2cbd3b133ed7e0" mode="widthFix"></image> </view> </list-item> <!-- 视频朋友圈内容 --> <list-item class="item uni-row"> <image class="avatar" src="/static/1.png" mode="scaleToFill"></image> <view class="content uni-row uni-column"> <text class="name">UNIAPP X</text> <text class="text">{{ text }}</text> <!-- 图片 / 视频 --> <view class="video"> <video :controls="false" class="video" poster="/static/1.png" src="https://qiniu-web-assets.dcloud.net.cn/video/sample/2minute-demo.mp4"></video> </view> <!-- 时间/点赞/评论按钮 --> <comment-line></comment-line> <!-- 点赞/评论信息列表 --> <comment></comment> </view> </list-item> <!-- 图文朋友圈内容 --> <list-item class="item uni-row" v-for="index in item_count"> <image class="avatar" src="/static/1.png" mode="scaleToFill"></image> <view class="content uni-row uni-column"> <text class="name">UNIAPP X {{ index }}</text> <text class="text">{{ text }}</text> <!-- 图片 / 视频 --> <view class="images uni-row"> <uni-moments-image :imageList="imageList"></uni-moments-image> </view> <!-- 定位 --> <text class="address mt-5">上海市 · 静安寺</text> <!-- 时间/点赞/评论按钮 --> <comment-line></comment-line> <!-- 点赞/评论信息列表 --> <comment></comment> </view> </list-item> </list-view> <!-- 自定义导航栏 --> <moments-header ref="header" :scrollTop="scrollTop"></moments-header> <!-- 点赞/评论 --> <comment-popup ref="commentPopup"></comment-popup> <!-- 评论输入框 --> <comment-input ref="commentInput"></comment-input> </template> <script> import MomentsHeader from './components/momentsHeader.uvue'; import CommentPopup from './components/comment-popup.uvue'; import CommentLine from './components/comment-line.uvue'; import CommentInput from './components/comment-input.uvue'; import Comment from './components/comment.uvue'; import uniMomentsImage from '../../components/uni-moments-image/uni-moments-image.uvue'; export default { components: { CommentLine, Comment, MomentsHeader, CommentInput, CommentPopup, uniMomentsImage }, data() { return { item_count: 20, listViewElement: null as UniListViewElement | null, refresherTriggered: false, refresherStyle: "none", text: `uni-app x,是下一代 uni-app,是一个跨平台应用开发引擎。uts是一门类ts的、跨平台的、新语言。uts在iOS端编译为swift、在Android端编译为kotlin、在Web端编译为js。`, imageList: [ "https://img1.baidu.com/it/u=1965663592,580944689&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1713286800&t=5c73d7f8aaa2a6f5114e659dd64e769d", "https://img0.baidu.com/it/u=3838093562,4126749835&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1713286800&t=a2cd3d4ac8c0f2024a348772577a9d0f", "https://img0.baidu.com/it/u=256816879,771155532&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1713286800&t=d5230b0cfdae75de3c452d973d302106", "https://img1.baidu.com/it/u=1965663592,580944689&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1713286800&t=5c73d7f8aaa2a6f5114e659dd64e769d", "https://img0.baidu.com/it/u=3838093562,4126749835&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1713286800&t=a2cd3d4ac8c0f2024a348772577a9d0f", "https://img0.baidu.com/it/u=256816879,771155532&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1713286800&t=d5230b0cfdae75de3c452d973d302106", ], scrollTop: 0, keyboardHeight: 200, // ios 默认键盘高度,这里占位 } }, onReady() { this.listViewElement = uni.getElementById<UniListViewElement>('listview'); // 监听点击评论事件 uni.$on('commentScrollEvent', (y: number) => this.listViewScrollByY(y - this.keyboardHeight + 40)); // 监听一次键盘高度回调 uni.$once('keyboardHeightEvent', (keyboardHeight: number) => { this.keyboardHeight = keyboardHeight; }); }, methods: { // 目标元素以外的touch事件 outsideTouchEvent() { // https://doc.dcloud.net.cn/uni-app-x/component/#methods (this.$refs['commentPopup'] as ComponentPublicInstance).$callMethod('hideCommentPopup'); // 隐藏点赞/评论 (this.$refs['commentInput'] as ComponentPublicInstance).$callMethod('hideKeyboard'); // 隐藏评论框与键盘 }, onScrollTolower(_ : ScrollToLowerEvent) { setTimeout(() => { this.item_count += 20 }, 300) }, scrollEvent(e : UniScrollEvent) { this.scrollTop = e.detail.scrollTop; }, listViewScrollByY(y : number) { this.listViewElement?.scrollBy(0, y) } } } </script> <style lang="scss" scoped> @import './index.scss'; </style> 这是nvue 好像 帮我改为vue2
07-18
<template> <el-table-column v-if="col.show && col.type != 'selection' && col.type != 'radio'" v-bind="col" :align="'center'" showOverflowTooltip > <template #header> <div class="table-header-div"> <span class="title-span">{{ col.label }}</span> <!-- 控制筛选按钮显隐 --> <template v-if="col.templet !== 'tool' && col.filter && col.prop"> <el-popover :visible="visible && col.prop === showKey" placement="bottom" :width="'fit-content'" > <template #reference> <!-- 筛选icon --> <div class="filter-container"> <el-icon @click.stop="toggleNameFilter(col.prop, col)" size="17.4" :class="{ 'filter-active': searchData[col.prop] }" > <Filter /> </el-icon> </div> </template> <div v-click-outside="handleClickOutside"> <!-- 输入 --> <el-input v-if="col.filter.filterFormType === 'input'" v-model="searchData[col.prop]" :autofocus="true" placeholder="请输入" v-bind="col.attrs" @input="applyNameFilter" clearable style="margin-top: 10px; width: 150px" /> <!--下拉 不需要获取数据 --> <template v-if="!col.filter.needGetList"> <el-select v-if="col.filter.filterFormType === 'select'" filterable :reserve-keyword="false" v-model="searchData[col.prop]" v-bind="col.attrs" @change="applyTagFilter" clearable style="margin-top: 10px; width: 150px" > <el-option v-for="item in col.filter.selectList" :key="item" :value="item.value" :label="item.name" /> </el-select> <FkSelectTree v-if="col.filter.filterFormType === 'select-tree'" v-model="searchData[col.prop]" v-bind="col.attrs" /> </template> <!--下拉 需要搜索获取后端接口数据 --> <template v-if="col.filter.needGetList"> <FkSelect v-if="col.filter.filterFormType === 'select'" v-bind="col.attrs" v-model="searchData[col.prop]" :sourceData="javaList" ></FkSelect> <!-- 多选树下拉 需要搜索获取后端接口数据 --> <FkSelectTree v-if="col.filter.filterFormType === 'select-tree'" v-model="searchData[col.prop]" v-bind="col.attrs" :data="javaList" :sourceData="javaList" ></FkSelectTree> </template> <!-- 日期 && 日期时间 --> <el-date-picker v-if=" col.filter.filterFormType === 'daterange' || col.filter.filterFormType === 'datetimerange' " style="width: 360px" v-model="searchData[col.prop]" :type="col.filter.filterFormType" range-separator="~" start-placeholder="开始时间" end-placeholder="结束时间" :format="col.dateType" @change="changeData($event, col.field, col.dateType)" /> <div class="mt" style="text-align: right"> <el-button type="info" link @click="cancelFilter(col.prop)">重置</el-button> <el-button type="primary" link @click="searchFilter">筛选</el-button> </div> </div> </el-popover> </template> </div> </template> <template #default="scope"> <!-- 显示图片 --> <template v-if="col.templet === 'image'"> <template v-if="col.prop"> <template v-if="Array.isArray(scope.row[col.prop])"> <template v-for="(item, index) in scope.row[col.prop]" :key="item"> <el-image :src="item" :preview-src-list="scope.row[col.prop]" :initial-index="index" :preview-teleported="true" :style="`width: ${col.imageWidth ?? 40}px; height: ${col.imageHeight ?? 40}px`" /> </template> </template> <template v-else> <el-image :src="scope.row[col.prop]" :preview-src-list="[scope.row[col.prop]]" :preview-teleported="true" :style="`width: ${col.imageWidth ?? 40}px; height: ${col.imageHeight ?? 40}px`" /> </template> </template> </template> <!-- 根据行的selectList属性返回对应列表--> <template v-else-if="col.templet === 'list'"> <template v-if="col.prop"> {{ (col.selectList ?? {})[scope.row[col.prop]] }} </template> </template> <!-- 格式化显示链接 --> <template v-else-if="col.templet === 'url'"> <template v-if="col.prop"> <el-link type="primary" :href="scope.row[col.prop]" target="_blank"> {{ scope.row[col.prop] }} </el-link> </template> </template> <!-- 格式化为价格 --> <template v-else-if="col.templet === 'price'"> <template v-if="col.prop"> {{ `${col.priceFormat ?? "¥"}${scope.row[col.prop]}` }} </template> </template> <!-- 格式化为百分比 --> <template v-else-if="col.templet === 'percent'"> <template v-if="col.prop">{{ scope.row[col.prop] }}%</template> </template> <!-- 显示图标 --> <template v-else-if="col.templet === 'icon'"> <template v-if="col.prop"> <template v-if="scope.row[col.prop].startsWith('el-icon-')"> <el-icon> <component :is="scope.row[col.prop].replace('el-icon-', '')" /> </el-icon> </template> <template v-else> <div class="i-svg:{{ scope.row[col.prop] }}" /> </template> </template> </template> <!-- 格式化时间 --> <template v-else-if="col.templet === 'date'"> <template v-if="col.prop"> {{ scope.row[col.prop] ? useDateFormat(scope.row[col.prop], col.dateFormat ?? "YYYY-MM-DD HH:mm:ss").value : "" }} </template> </template> <!-- 格式代码集 --> <template v-else-if="col.templet === 'sys-code'"> <FkSysCodeLable v-if="col.prop" v-model="scope.row[col.prop]" :code="col.sysCodeSetCode" /> </template> <!-- 可复制 --> <template v-else-if="col.templet === 'copy'"> <el-text>{{ scope.row[col.prop] }}</el-text> <copy-button v-if="scope.row[col.prop]" :text="scope.row[col.prop]" style="margin-left: 2px" /> </template> <!-- yes-no --> <template v-else-if="col.templet === 'yes-no'"> <el-tag :type="scope.row[col.prop] == '1' ? 'success' : 'info'"> {{ scope.row[col.prop] == "1" ? "启用" : "禁用" }} </el-tag> </template> <!-- translate --> <template v-else-if="col.templet === 'translate'"> {{ scope.row[col.prop + "Name"] }} </template> </template> </el-table-column> </template> <script setup lang="ts"> import _ from "lodash"; import SysOrgAPI from "@/api/zxyy-org-service/sysOrg/sysOrg.api"; import { useSysCodeStore } from "@/store"; const sysCodeStore = useSysCodeStore(); import moment, { MomentInput } from "moment"; // 定义接收的属性 const props = defineProps<{ col: any; permPrefix?: any; lastSelectFormData?: any }>(); // 重方法 const emit = defineEmits(["filter", "cancelFilter"]); // 解决办法:声明一下键值对的类型 type objType = { [key: string]: any; }; // 表头筛选处理 const showKey = ref(); // 当前展示哪个筛选窗 const visible = ref(false); // 手动控制筛选窗显隐 const searchData = ref<objType>({}); // 搜索参数 每个表头字段 // 触发筛选 async function toggleNameFilter(key?: string, col?: any) { if (!key) { return; } // console.log(key, item); if (col.filter.needGetList) { await getJavaList(col); // 调用后端接口 获取下拉数据 } if (visible.value && showKey.value && showKey.value !== key) { visible.value = false; // fetchPageData(lastFormData, true); } showKey.value = key; visible.value = true; } // 某些下拉数据 例如下拉大数据有500条 直接赋值会导致表格卡顿 通过点击表头再去接口获取数据赋值就不会影响表格的渲染 // (列里面数据回显使用后端给的中文,或者将javaList赋值给item的selectList) let javaList = ref(); let javaListObj = ref<objType>({}); const getJavaList = async (col: any) => { console.log("getJavaList"); if (javaListObj.value[col.filter.filterCodeSetId]) { javaList.value = javaListObj.value[col.filter.filterCodeSetId]; console.log("getJavaList-javaListObj", javaList.value); return; } if (col.filter.filterCodeSetId == "org") { console.log("filterCodeSetId", col.filter.filterCodeSetId); javaList.value = await SysOrgAPI.getSysOrgOptions(); } if (col.filter.filterCodeSetId == "person") { // javaList.value = await SysOrgAPI.getSysOrgOptions(); } if (col.filter.filterCodeSetId == "sys-code") { javaList.value = sysCodeStore.getSysCodeSetItems(col.sysCodeSetCode); } console.log("javaList", javaList.value); javaListObj.value[col.filter.filterCodeSetId] = javaList.value; console.log("javaListObj", javaListObj.value); }; // 单独过滤 const applyNameFilter = () => { // Filtering logic can be customized if needed }; const applyTagFilter = () => { // Filtering logic can be customized if needed }; // 时间格式化 const changeData = (value: MomentInput[], key: string | number, dateType: string | undefined) => { // console.log(value, key, dateType); if (!_.isEmpty(value)) { searchData.value[key][0] = value[0] ? moment(value[0]).format(dateType) : ""; searchData.value[key][1] = value[1] ? moment(value[1]).format(dateType) : ""; } else { searchData.value[key] = []; } }; // 单个重置 function cancelFilter(key: string) { searchData.value[key] = undefined; emit("cancelFilter", key); // let filters = props.lastSelectFormData.filters.filter((o: any) => { // return o.column != showKey.value; // }); // props.lastSelectFormData.filters = filters; // let headers = props.lastSelectFormData.headers.filter((o: any) => { // return o.field != showKey.value; // }); // props.lastSelectFormData.headers = headers; visible.value = false; // console.log("cancelFilter", searchData.value); // fetchPageData(lastFormData, true); //emit("cancelFilter", key); //emit("filter", props.lastSelectFormData); } // 筛选 const searchFilter = () => { console.log("searchFilter"); visible.value = false; let filters = []; let headers = []; for (const key in searchData.value) { const col = props.col; if (col && Object.hasOwnProperty.call(searchData.value, key) && searchData.value[key]) { filters.push({ column: key, value: props.col.filter.filterValueType === "string" ? searchData.value[key].join(",") : searchData.value[key], type: col.filter.filterType, operator: col.filter.filterOperator, }); headers.push({ field: key, name: col.label, dataType: col.filter.filterDataType, codeSetId: col.filter.filterCodeSetId, }); } } props.lastSelectFormData.filters = filters; props.lastSelectFormData.headers = headers; emit("filter", props.lastSelectFormData); console.log("searchFilter1"); console.log("searchFilter2", props.lastSelectFormData); }; // 监听外部传入的 modelValue 变化 watch( () => props.lastSelectFormData.filters, (newValue) => { if (!newValue || newValue.length == 0) { searchData.value = {}; visible.value = false; } }, { immediate: true } ); // 点击外部区域关闭弹窗 import { ClickOutside as vClickOutside } from "element-plus"; defineComponent({ directives: { "click-outside": vClickOutside }, // 局部注册 }); const handleClickOutside = () => { visible.value = false; }; </script> <style lang="scss" scoped> :deep(.el-table) { // height: 700px; /* 设置表格整体固定高度 */ thead { .cell { display: flex; min-width: 100px; position: relative; .table-header-div { // flex: 1; display: flex; .title-span { flex-grow: 1; word-break: break-word; /* 允许单词在任何地方断行 */ } .el-only-child__content { height: 23px; } .icon-span { flex-shrink: 0; margin-top: 1px; margin-left: 5px; cursor: pointer; /* 防止缩小 */ /* 给图标和标题之间添加一些间距 */ } } .caret-wrapper { margin-top: 5px; } } } } .filter-container { display: flex; justify-content: center; align-items: center; } /* 筛选图标激活状态样式 */ .el-icon.filter-active { color: #409eff !important; /* Element UI的主题蓝色 */ } </style> 优化,点击弹窗外部,自动关闭弹窗,点击嵌套弹窗,不关闭主弹窗
最新发布
07-31
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值