实现点击空白区域隐藏下拉弹窗

背景


中后台项目依赖Element UI 组件库,组件库中Select 选择器、Popover 弹出框等组件弹出内容后,点击组件外部区域都可以让内容收回。

但是我们的页面中有iframe标签,点击iframe标签时,弹出内容并没有收回。

为了解决这一个问题,我们需要调研一下Element UI 是如何实现这个功能的。

功能描述


点击下图中的输入框 A,显示弹窗B,点击 A B 以外的区域,弹窗B 收回。
在这里插入图片描述

思路


需求点

  1. 实现select弹出框,能让弹出框显示、隐藏切换
  2. 实现一个点击组件外部区域,能通知到弹出窗状态切换的功能
  3. 可以复用,通用。

思路一:利用CSS伪类:focus :focus-within 通过样式控制

1. 兼容性在这里插入图片描述
在这里插入图片描述
2. 是否支持Iframe
支持

3. 示例代码

<input class="select" type="text"> <div class="pop-wrap">下拉框</div>
.select:focus + .pop-wrap {
   
    display: block;
}

4. 备注
不容易封装,对组件结构有要求,必须按照规定的写法写,很难实现即插即用。
组件html布局比较固定,常规弹窗类组件应该遵循单例模式,这里无法做到。
点击弹出内容区域的时候,焦点会失去,需要单独处理。

思路二:监听focus聚焦、blur失焦事件实现

监听document的聚焦事件,通过聚焦发生时的target来控制弹出哪一个弹窗。

1. 兼容性
在这里插入图片描述
focus事件不支持冒泡模式,需要用捕获模式监听。

2. 是否支持Iframe
支持

3. 示例代码

// focus事件监听:
document.addEventListener('focus', handleFn, true);
// focusin事件监听
document.addEventListener('focusin', handleFnr);

4. 备注
其实用聚焦事件与用mouseup事件的处理方式相似,区别在于点击浏览器之外的区域或点击Iframe时,失焦事件会触发,但是mouseup事件不会触发,这也就导致了用mouseup事件在部分场景会失效。
Element UI 采用的方案就是mouseup,至于如何解决mouseup方案带来的问题,接下来会说明。

事件触发的流程:mouseup事件 → focus事件/blur事件 → 事件处理函数 → 弹出/隐藏弹窗

focus/blur事件虽然解决了点击iframe不触发mouseup的问题,但是相比mouseup而言过程有点不可控,mouseupfocus这一步有时候不受控制。

例如:
在页面中聚焦事件后打开弹窗,这个时候你切换应用,这时候会触发blur事件,回到浏览器窗口时又触发了focus事件,这两步操作其实是多余的。

当然如果你正需要做一个当焦点不在你的网页上时,显示一个蒙层来保证隐私,focus是一个很好的选择。

思路三:监听mouseup事件实现

监听documentmouseup事件发生时的target来控制弹出哪一个弹窗

1. 兼容性

2. 是否支持
iframe

3. 示例代码

// mouseup事件监听:
document.addEvent
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 您可以通过在QLineEdit周围放置一个透明的QWidget来实现这个功能。当用户单这个QWidget时,您可以隐藏QCalendarWidget,当用户单QLineEdit时,您可以显示QCalendarWidget。 以下是一个简单的代码示例,它实现了这个功能: ``` #include <QtWidgets> class DateSelectionDialog : public QDialog { Q_OBJECT public: DateSelectionDialog(QWidget *parent = nullptr) : QDialog(parent) { QVBoxLayout *layout = new QVBoxLayout(this); m_calendar = new QCalendarWidget(this); layout->addWidget(m_calendar); connect(m_calendar, &QCalendarWidget::clicked, this, &DateSelectionDialog::onCalendarClicked); } QDate selectedDate() const { return m_selectedDate; } signals: void dateSelected(const QDate &date); private slots: void onCalendarClicked(const QDate &date) { m_selectedDate = date; emit dateSelected(date); hide(); } private: QCalendarWidget *m_calendar; QDate m_selectedDate; }; class DateLineEdit : public QLineEdit { Q_OBJECT public: DateLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) { setReadOnly(true); m_backgroundWidget = new QWidget(this); m_backgroundWidget->setFixedSize(size()); m_backgroundWidget->setStyleSheet("background-color: transparent;"); m_backgroundWidget->lower(); connect(m_backgroundWidget, &QWidget::clicked, this, &DateLineEdit::onBackgroundClicked); connect(this, &QLineEdit::clicked, this, &DateLineEdit::onClicked); } private slots: void onClicked() { QPoint pos(0, height()); pos = mapToGlobal(pos); m_dateSelectionDialog.move(pos); m_dateSelectionDialog.show(); } void onBackgroundClicked() { m_dateSelectionDialog.hide(); } void onDateSelected(const QDate &date) { setText(date.toString(Qt::ISODate)); } private: DateSelectionDialog m_dateSelectionDialog; QWidget *m_backgroundWidget; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); DateLineEdit dateLineEdit; dateLineEdit.show(); return app.exec(); } #include "main.moc" ``` 在这个代码示例中,我们创建了一个名为DateLineEdit的自定义QLineEdit,它包含一个DateSelectionDialog对象和一个透明的QWidget对象。当用户单QLineEdit时,我们显示DateSelectionDialog。当用户单透明QWidget时,我们隐藏DateSelectionDialog。当用户选择日期时,我们使用setText()方法设置QLineEdit中的文本。另外,当用户单空白区域时,DateSelectionDialog会自动隐藏。 ### 回答2: 要实现空白区域隐藏日历,可以通过以下步骤来实现: 1. 首先,需要在页面上布置一个包含日历的元素,可以是一个出框、一个下菜单或一个固定位置的日历区域。 2. 我们可以利用HTML和CSS来创建日历的UI界面,包括日期的选择、日历的显示等。 3. 使用JavaScript来实现空白区域隐藏日历的功能。可以通过给整个页面添加一个点事件监听器,当用户点页面上的任意区域时触发事件。 4. 在点事件中,我们需要判断点区域是否是日历区域的外部区域。可以通过比较点的坐标和日历区域的位置来判断。如果点在日历区域内部,则不做任何操作;如果点在日历区域外部,则隐藏日历。 5. 当用户点了日历区域外部时,可以通过修改日历元素的样式来隐藏日历。可以使用CSS中的display属性或visibility属性来控制日历的显示与隐藏。 6. 最后,为了增强用户体验,可以在实现的基础上添加一些附加功能,比如当用户点其他区域时,如果日历已经显示,则隐藏日历;如果日历已经隐藏,则不做任何操作。 通过以上步骤,就可以实现空白区域隐藏日历的功能了。这样用户可以方便地在页面上选择日期,并且不会干扰到其他的操作。 ### 回答3: 要实现空白区域日历隐藏,可以通过以下步骤: 1. 监听空白区域的点事件:首先,需要在页面中添加一个透明的或者不可见的元素,覆盖整个页面,作为空白区域。然后,使用JavaScript或者其他适用的技术,给这个元素绑定一个点事件监听器。 2. 判断点事件来源:在点事件监听器中,需要判断点事件的来源。如果点事件触发的元素不属于日历组件,则执行隐藏日历的操作,否则忽略该点事件。 3. 隐藏日历:如果点事件的来源不是日历组件,那么就执行隐藏日历的操作。隐藏日历可以通过修改日历组件的样式或者添加一个class来实现。可以设置日历组件为display: none;,或者添加一个样式类,该类将日历元素的display属性设置为none。 这样,当用户点空白区域时,就会触发点事件,通过判断事件来源是否为日历组件,来决定是否隐藏日历。这种实现方式可以确保只在非日历组件区域隐藏日历,而在点日历组件时不会隐藏日历。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值