原生Vue 实现右键菜单组件功能

下面是详细的“原生Vue 实现右键菜单组件功能”的攻略:

1. 准备工作

要实现右键菜单组件,我们首先要准备好 Vue 以及相关依赖包,这里我以安装 Vue 3.x 版本为例。

在控制台运行以下命令:

npm install vue@next

另外,我们需要使用 popper.js 依赖库来实现菜单的弹出和定位,通过以下命令安装:

npm install @popperjs/core

2. 创建右键菜单组件

接下来,我们可以创建一个名为 ContextMenu.vue 的 Vue 单文件组件,并在其中编写右键菜单的 HTML 结构和样式。以下是一个简单的示例:

<template>
  <div class="context-menu" :style="{ top: position.top + 'px', left: position.left + 'px' }">
    <ul>
      <li v-for="(item, index) in items" :key="index" @click="item.action">{{ item.label }}</li>
    </ul>
  </div>
</template>

<script>
import { onMounted, onUnmounted, ref } from 'vue';
import { createPopper } from '@popperjs/core';

export default {
  props: {
    items: {
      type: Array,
      default: () => [],
    },
    position: {
      type: Object,
      default: () => ({ top: 0, left: 0 }),
    },
  },
  setup(props) {
    const reference = ref(null);
    const popper = ref(null);

    onMounted(() => {
      popper.value = createPopper(reference.value, props.position, {
        placement: 'right-start',
      });
    });

    onUnmounted(() => {
      popper.value.destroy();
      popper.value = null;
    });

    return {
      reference,
      popper,
    };
  },
};
</script>

<style scoped>
.context-menu {
  position: fixed;
  z-index: 999;
  background: white;
  border: 1px solid #ccc;
  list-style: none;
  padding: 0;
  margin: 0;
}

.context-menu ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
.context-menu li {
  padding: 8px 12px;
  cursor: pointer;
}
.context-menu li:hover {
  background: #f2f2f2;
}
</style>

在这个示例中,我们使用了 Popper.js 实现了菜单的定位和弹出,同时在 props 中接收菜单项数据 items 和菜单位置信息 position,并根据数据动态生成菜单项的内容。

3. 在页面中使用右键菜单组件

实现菜单组件之后,我们需要在业务页面中使用该组件。以下是一个简单的示例:

<template>
  <div @contextmenu.prevent="showContextMenu" @click="hideContextMenu">
    <p>
      右键点击此处
    </p>
    <ContextMenu v-if="isContextMenuVisible" :position="contextMenuPosition" :items="contextMenuItems" />
  </div>
</template>

<script>
import ContextMenu from './ContextMenu.vue';

export default {
  components: {
    ContextMenu,
  },
  data() {
    return {
      isContextMenuVisible: false,
      contextMenuPosition: { top: 0, left: 0 },
      contextMenuItems: [
        {
          label: '菜单项1',
          action: () => {
            console.log('点击了菜单项1');
          },
        },
        {
          label: '菜单项2',
          action: () => {
            console.log('点击了菜单项2');
          },
        },
      ],
    };
  },
  methods: {
    showContextMenu(e) {
      this.isContextMenuVisible = true;
      this.contextMenuPosition = { top: e.clientY, left: e.clientX };
    },
    hideContextMenu() {
      this.isContextMenuVisible = false;
    },
  },
};
</script>

在这个示例中,我们在父组件的根元素上绑定了 contextmenu 事件,并传入了一个预设方法 showContextMenu,使右键点击事件被触发时,动态计算菜单位置和菜单项数据,并将变量 isContextMenuVisible 设置为 true,从而显示菜单。同时,在 click 事件中调用 hideContextMenu 方法,以隐藏菜单。

我们在页面中使用创建的 ContextMenu 组件,并传入菜单项数据 contextMenuItems 和位置信息 contextMenuPosition,这些信息都是在 showContextMenu 方法中动态计算得到的。

4. 添加菜单项动态更新的示例

接下来我们添加一个菜单项动态更新的示例,当菜单项数据发生变化时,菜单项应该自动更新。

我们可以在父组件中添加一个 data 属性 menuItemsUpdated,并在 mounted 生命钩子中创建一个定时器,每隔一段时间更新菜单项数据:

<template>
  <div @contextmenu.prevent="showContextMenu" @click="hideContextMenu">
    <p>
      右键点击此处
    </p>
    <ContextMenu v-if="isContextMenuVisible" :position="contextMenuPosition" :items="contextMenuItems" />
  </div>
</template>

<script>
import ContextMenu from './ContextMenu.vue';

export default {
  components: {
    ContextMenu,
  },
  data() {
    return {
      isContextMenuVisible: false,
      contextMenuPosition: { top: 0, left: 0 },
      contextMenuItems: [
        {
          label: '菜单项1',
          action: () => {
            console.log('点击了菜单项1');
          },
        },
        {
          label: '菜单项2',
          action: () => {
            console.log('点击了菜单项2');
          },
        },
      ],
      menuItemsUpdated: false,
    };
  },
  mounted() {
    setInterval(() => {
      const newItems = [
        {
          label: '菜单项1(已更新)',
          action: () => {
            console.log('点击了菜单项1(已更新)');
          },
        },
        {
          label: '菜单项2(已更新)',
          action: () => {
            console.log('点击了菜单项2(已更新)');
          },
        },
      ];
      this.contextMenuItems = newItems;
      this.menuItemsUpdated = !this.menuItemsUpdated;
    }, 5000);
  },
  methods: {
    showContextMenu(e) {
      this.isContextMenuVisible = true;
      this.contextMenuPosition = { top: e.clientY, left: e.clientX };
    },
    hideContextMenu() {
      this.isContextMenuVisible = false;
    },
  },
};
</script>

这个示例中,我们使用 setInterval 创建了一个定时器,在每次定时器回调中重新设置菜单项数据,并且每次 data 中的 menuItemsUpdated 属性值都会改变,这样就能触发组件的重新渲染和列表的更新。

注意:由于使用了 data 中的属性修改触发更新的方式,因此 contextMenuItems 的初始化应该使用函数的方式,即 default: () => []

总结

以上就是实现右键菜单组件的完整攻略,包含组件的创建、样式与事件的处理,以及在页面中的应用和菜单项动态更新的示例。通过实现上述内容,我们可以轻松实现自定义的右键菜单功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:原生Vue 实现右键菜单组件功能 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Vue使用Proxy代理后仍无法生效的解决

    Vue使用Proxy代理后仍无法生效的解决 问题描述 在开发Vue项目过程中,使用了Proxy代理进行数据劫持,但是在实际运行过程中发现代理并没有生效,也就是说数据并没有被劫持。这种情况的原因主要是: 必须确保Vue实例中的data数据是一个对象,否则无论如何Proxy都无法代理成功。 Vue3中重写了响应式系统,导致Vue2中的一些Proxy语法在Vue3…

    other 2023年6月27日
    00
  • java格式化数字操作 NumberFormat及DecimalFormat

    让我为您讲解一下“java格式化数字操作 NumberFormat及DecimalFormat”的攻略。 1. NumberFormat及DecimalFormat简介 NumberFormat是java.util包中的一个抽象类,是将数字格式化为字符串的基类,它提供了很多方法来格式化数字,例如将数字格式化为货币、百分数等。 DecimalFormat是Nu…

    other 2023年6月26日
    00
  • WPF基本控件介绍

    WPF基本控件介绍 本文将介绍WPF中常用的基本控件,包括Label、Button、TextBox、RadioButton、CheckBox、ComboBox、ListBox、ListView和DataGrid,内容将涵盖控件的特性、用法和示例说明。 Label控件 Label控件用于显示文本,它有以下特性: Content:控件显示的文本内容; 下面是一个…

    other 2023年6月27日
    00
  • string类的append方法

    在C++中,string类的append方法是用于将字符串添加到另一个字符串的末尾。以下是一个完整攻略,介绍了如何使用string的append方法。 步骤1:使用append方法 在C++中,我们可以使用string类append方法将字符串添加到另一个字符串的末尾。以下是一个示例: #include <iostream> #include &…

    other 2023年5月6日
    00
  • 详解C语言未初始化的局部变量是多少

    首先,未初始化的局部变量在 C 语言中的默认值是不确定的,因为它们未被赋初值。这意味着它们的值可能是任何值,包括0、1、甚至负数,因为它们是分配在栈上的不确定空间。 如果你的程序依赖于默认值,那么你就需要使用赋值语句来初始化变量。这个问题的解决方法有两种: 1.手动初始化:在定义变量的同时给它指定初值。例如: int x = 0; //初始化为0 char …

    other 2023年6月20日
    00
  • xiv存储操作

    XIV是IBM公司的一种存储设备,提供高性能、高可靠性和高可扩展性的存储解决方案。以下是XIV存储操作的完整攻略,包括以下步骤: 连接XIV存储设备 创建卷 示例1:创建卷 示例2:删除卷 连接XIV存储设备 要连接XIV存储设备,需要使用XIV Graphical User Interface(GUI)。以下是连接XIV存储设备步骤: 打开XIV GUI:…

    other 2023年5月6日
    00
  • C++模拟实现JDK中的ArrayList和LinkedList

    C++模拟实现JDK中的ArrayList和LinkedList 在C++中,可以使用STL中的vector和list来实现类似于JDK中的ArrayList和LinkedList的功能。下面是使用C++ STL实现ArrayList和LinkedList的示例。 ArrayList的实现 #include <iostream> #include…

    other 2023年5月5日
    00
  • BAT脚本批量修改文件名的两种方法

    下面是详细讲解“BAT脚本批量修改文件名的两种方法”的完整攻略。 1. 前言 在日常电脑使用过程中,我们经常需要批量修改文件名。传统的方式是手动一个一个修改,这样既费时又容易出错。而使用BAT脚本批量修改则可以省去人工操作,提高效率。 本文将介绍两种利用BAT脚本批量修改文件名的方法,分别是使用“for”循环和使用“ren”命令。 2. 使用“for”循环 …

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部