首先可以将菜单封装成一个组件,然后在组件中实现相关逻辑,以减少模板代码。要实现点击菜单外空白区域关闭菜单的功能,在uni-app开发中的实现大致可以分为 只兼容web端 和 兼容所有端 两种方式。由于web端可以直接访问 document,所以可以直接监听 document 的 click 事件,然后判断当前点击的 target 是否包含在菜单范围中,如果不在的话就关闭菜单,示例如下:export default { name: "DemoDropdown", props: { visible: { type: Boolean, default: false } }, computed: { innerVisible: { get() { return this.visible; }, set(value) { this.$emit("update:visible", value); } } }, watch: { innerVisible: { handler(visible) { // 菜单弹出后开始监听document的click事件,关闭后移除监听 if (visible) { this.createDocumentClickListener(); } else { this.removeDocumentClickListener(); } }, immediate: true } }, beforeDestroy() { this.removeDocumentClickListener(); }, methods: { createDocumentClickListener() { setTimeout(() => { document.documentElement.addEventListener("click", this.documentClickHandler); }, 100); }, removeDocumentClickListener() { document.documentElement.removeEventListener("click", this.documentClickHandler); }, documentClickHandler(event) { // 点击元素不包含在菜单范围中 -> 关闭菜单 if (!this.$el.contains(event.target)) { this.innerVisible = false; } } } };由于部分端不能直接访问 document(或者是没有 document 的概念,例如小程序端、App端等),我们可以手动在菜单下方添加一个透明的全屏蒙层,当点击蒙层时执行关闭菜单的操作,示例如下:<template> <view class="demo-dropdown"> <view class="demo-dropdown__modal" @tap="innerVisible = false"></view> <view class="demo-dropdown__inner"> <!-- 菜单内容 --> </view> </view> </template>.demo-dropdown__modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 10; } .demo-dropdown__inner { position: relative; // ...其他样式 z-index: 12; }
首先可以将菜单封装成一个组件,然后在组件中实现相关逻辑,以减少模板代码。
要实现点击菜单外空白区域关闭菜单的功能,在uni-app开发中的实现大致可以分为
只兼容web端
和兼容所有端
两种方式。document
,所以可以直接监听document
的click
事件,然后判断当前点击的target
是否包含在菜单范围中,如果不在的话就关闭菜单,示例如下:document
(或者是没有document
的概念,例如小程序端、App端等),我们可以手动在菜单下方添加一个透明的全屏蒙层,当点击蒙层时执行关闭菜单的操作,示例如下: