右键菜单

//父组件使用
<right-menu :visible.sync="visible" :list="list"></right-menu>
.sync修饰符
在vue中说到数据绑定的时候第一时间想到的就是v-model,但是因为每个组件只能绑定一个v-model,如果其他props也要实现双向绑定的效果该怎么办呢? 简单的方法是子组件向父组件发送一个事件,父组件监听该事件,然后更新props,.sync就是这种方法的简化。
sync修饰符的作用
1.当我们需要在子组件中改变props接收的值并且需要同步到父组件中的时候需要用到.sync修饰符。
2.如果一个组件的多个props都要实现双向绑定,只需要每个props加sync修饰符。


//子组件right-menu
<template>
	<div v-if="visible">
		<el-menu class="contextmenu" :style="style" @click="handleClick">
			<el-menu-item v-for="item in list" :key="item.key">
				<span>{{ item.text }}</span>
			</el-menu-item>
		</el-menu>
	</div>
</template>


<script>
export default {
	name: "ContextMenu",
	props: {
		visible: {
			type: Boolean,
			default: false,
		},
		list: {
			type: Array,
			required: true,
			default: () => [],
		},
	},
	data() {
		return {
			left: 0,
			top: 0,
			target: null,
		};
	},
	computed: {
		style() {
			return {
				left: this.left + "px",
				top: this.top + "px",
			};
		},
	},
	created() {
		const clickHandler = () => this.closeMenu();
		const contextMenuHandler = (e) => {
			e.preventDefault();
			this.setPosition(e);
		};
		window.addEventListener("click", clickHandler);
		window.addEventListener("contextmenu", contextMenuHandler);
		this.$emit("hook:beforeDestroy", () => {
			window.removeEventListener("click", clickHandler);
			window.removeEventListener("contextmenu", contextMenuHandler);
		});
	},
	methods: {
		closeMenu() {
			this.$emit("update:visible", false);//修改父组件的visible
		},
		setPosition(e) {
			// 获取菜单的宽高
			const menu = document.querySelector(".contextmenu");
			const menuHeight = menu.offsetHeight;
			// 获取窗口的可视高度
			const windowHeight = window.innerHeight;
			
			this.left = e.clientX;
			
			// 计算菜单的上边位置
			if (e.clientY + menuHeight > windowHeight) {
				const top = e.clientY - menuHeight;
				if (top < 0) {
					this.top = 0; // 确保菜单不会超出顶部
				} else {
					// 如果菜单的底部超出了窗口的底部
					this.top = top;
				}
			} else {
				// 如果菜单的底部没有超出窗口的底部
				this.top = e.clientY;
			}
			
			this.target = e.target;
		},
		handleClick({ key }) {
			const _component = this.list.filter((item) => item.key === key)[0]
				.component;
			if (_component) {
				this.$emit("contextMenuClick", _component, key);
			}
			this.closeMenu();
		},
	},
};
</script>


<style lang="scss" scoped>
.contextmenu {
	position: fixed;
	z-index: 1000;
	border-radius: 4px;
	border: 1px lightgrey solid;
	box-shadow: 4px 4px 10px lightgrey !important;
}
</style>


posted @   Code_Lzh  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示