├── .browserslistrc
├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── .prettierrc.json
├── PUBLISH.md
├── README.md
├── babel.config.js
├── commitlint.config.js
├── package.json
├── src
├── components
│ └── right-menu.vue
└── main.js
├── vue.config.js
├── webstorm.config.js
└── yarn.lock
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | # 对所有文件有效
4 | [*]
5 | charset = utf-8
6 | tab_width = 2
7 | indent_style = space
8 | indent_size = 2
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
7 | parserOptions: {
8 | parser: "babel-eslint"
9 | },
10 | rules: {
11 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
12 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
13 | "prettier/prettier": "error", // prettier标记的地方抛出错误信息
14 | "spaced-comment": [2, "always"], // 注释后面必须写两个空格
15 | "@typescript-eslint/no-explicit-any": ["off"] // 关闭any校验
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "useTabs": false,
4 | "endOfLine": "auto",
5 | "singleQuote": false,
6 | "semi": true,
7 | "trailingComma": "none",
8 | "bracketSpacing": true
9 | }
10 |
--------------------------------------------------------------------------------
/PUBLISH.md:
--------------------------------------------------------------------------------
1 | ## 新版本推送规范
2 |
3 | - 对插件进行修改
4 |
5 | - 执行 `yarn build` 来生成打包后的文件
6 |
7 | - 修改`package.json`中的版本号
8 |
9 | - 提交你的修改
10 |
11 | - 运行`package.json`中的`changelog`命令来生成更新记录
12 |
13 | - 最后将项目推送到你的仓库,然后为主仓库创建一个Pull request
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-right-click-menu · [](https://www.npmjs.com/package/vue-right-click-menu) [](https://yarnpkg.com/package/vue-right-click-menu) [](https://github.com/likaia/vue-right-click-menu) [](https://github.com/likaia/vue-right-click-menu/issues) [](https://github.com/likaia/vue-right-click-menu/network/members) [](https://github.com/likaia/vue-right-click-menu/stargazers)
2 | 支持vue的浏览器右键菜单插件,效果图如下:
3 |
4 | 
5 |
6 | ## 插件安装
7 | ```bash
8 | yarn add vue-right-click-menu
9 |
10 | # or
11 |
12 | npm install vue-right-click-menu --save
13 | ```
14 | ## 插件使用
15 |
16 | * 在项目的入口文件`main.ts/main.js`中加入下述代码
17 | ```javascript
18 | import rightMenu from "vue-right-click-menu";
19 |
20 | Vue.use(rightMenu);
21 | ```
22 | * 在你的业务代码中,在元素上绑定`v-right-click`,然后传对应的参数即可.
23 | ```vue
24 |
25 |
29 |
30 |
72 | ```
73 | ### 参数说明
74 | 如示例代码所示,在元素上绑定指令,在computed中定义一个对象,传菜单内容和与之对应的事件处理函数就可以了。
75 |
76 | 接下来就跟大家讲下对象里每个属性的意义:
77 | * this 即当前vue实例,便于在处理函数中能访问到当前vue实例中的内容
78 | * text 类型为数组,即右键菜单要显示的内容
79 | * 数组内的内容分为字符串或对象,如果为字符串这一项默认是可以点击的
80 | * 如果你想让某个选项无法点击,则传一个对象
81 | * content 要显示的文字内容,字符串类型
82 | * status 是否禁用,boolean类型
83 | * 点击事件接受一个参数,具体写法可参考示例代码
84 | * handler 事件处理函数,函数的顺序要与text数组内的文本顺序相对应
85 |
86 | ## 写在最后
87 | 至此,插件的所有使用方法就介绍完了。
88 |
89 | 该插件仅支持Vue2.x的项目,Vue3.x项目请移步: [vue-right-click-menu-next](https://github.com/likaia/vue-right-click-menu-next)
90 |
91 | 想进一步了解插件源码的请移步插件的GitHub仓库:[vue-right-click-menu](https://github.com/likaia/vue-right-click-menu)
92 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"]
3 | };
4 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = { extends: ["@commitlint/config-angular"] };
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-right-click-menu",
3 | "version": "1.1.1",
4 | "description": "支持vue的右键菜单插件",
5 | "private": false,
6 | "main": "dist/vueRightMenuPlugin.common.js",
7 | "publisher": "magicalprogrammer@qq.com",
8 | "scripts": {
9 | "build": "vue-cli-service build --target lib --name vueRightMenuPlugin src/main.js"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/likaia/vue-right-click-menu.git"
14 | },
15 | "keywords": [
16 | "vuejs",
17 | "vue",
18 | "rightMenu",
19 | "右键菜单",
20 | "vueRightMenu"
21 | ],
22 | "author": "likaia",
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/likaia/vue-right-click-menu/issues"
26 | },
27 | "homepage": "https://github.com/likaia/vue-right-click-menu#readme",
28 | "dependencies": {
29 | "core-js": "^3.6.5",
30 | "vue": "^2.6.11"
31 | },
32 | "devDependencies": {
33 | "@vue/cli-plugin-babel": "~4.5.0",
34 | "@vue/cli-plugin-eslint": "~4.5.0",
35 | "@vue/cli-service": "~4.5.0",
36 | "@vue/eslint-config-prettier": "^6.0.0",
37 | "babel-eslint": "^10.1.0",
38 | "eslint": "^6.7.2",
39 | "eslint-plugin-prettier": "^3.1.3",
40 | "eslint-plugin-vue": "^6.2.2",
41 | "node-sass": "^4.12.0",
42 | "prettier": "^1.19.1",
43 | "sass-loader": "^8.0.2",
44 | "vue-template-compiler": "^2.6.11"
45 | },
46 | "config": {
47 | "commitizen": {
48 | "path": "./node_modules/cz-conventional-changelog"
49 | }
50 | },
51 | "husky": {
52 | "hooks": {
53 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/components/right-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
56 |
57 |
58 |
69 |
70 |
133 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import rightMenu from "./components/right-menu.vue";
2 | import Vue from "vue";
3 |
4 | // 挂载后的dom节点
5 | let menuVM = null;
6 |
7 | /**
8 | * 将组件挂在到节点上
9 | * @param comp 需要挂载的组件
10 | * @param prop 向组件传的参数
11 | */
12 | const creatComp = function(comp, prop) {
13 | // 创建组件
14 | const app = Vue.extend(comp);
15 | // 创建一个div元素
16 | const divEle = document.createElement("div");
17 | // 将创建的div元素挂载追加至body里
18 | document.body.appendChild(divEle);
19 | // 将组件挂载至刚才创建的div中, 使用propsData进行传参
20 | new app({
21 | propsData: {
22 | ...prop
23 | }
24 | }).$mount(divEle);
25 | // 返回挂载的元素,便于操作
26 | return divEle;
27 | };
28 |
29 | export default {
30 | install(Vue) {
31 | // 监听全局点击,销毁右键菜单dom
32 | document.body.addEventListener("click", () => {
33 | if (menuVM != null) {
34 | // 销毁右键菜单DOM
35 | document.body.removeChild(document.getElementById("rightMenuDom"));
36 | menuVM = null;
37 | }
38 | });
39 | Vue.directive("rightClick", (el, binding) => {
40 | // 指令绑定元素元素是否存在判断
41 | if (el == null) {
42 | throw "右键指令错误:元素未绑定";
43 | }
44 | el.oncontextmenu = function(e) {
45 | if (menuVM != null) {
46 | // 销毁上次触发的右键菜单DOM
47 | document.body.removeChild(document.getElementById("rightMenuDom"));
48 | menuVM = null;
49 | }
50 | const textArray = binding.value.text;
51 | const handlerObj = binding.value.handler;
52 | const parameter = binding.arg;
53 | // 菜单选项与事件处理函数是否存在
54 | if (textArray == null || handlerObj == null) {
55 | throw "右键菜单内容与事件处理函数为必传项";
56 | }
57 | // 事件处理数组
58 | const handlerArray = [];
59 | // 处理好的右键菜单
60 | const menuList = [];
61 | // 将事件处理函数放入数组中
62 | for (const key in handlerObj) {
63 | handlerArray.push(handlerObj[key]);
64 | }
65 | if (textArray.length !== handlerArray.length) {
66 | // 文本数量与事件处理不对等
67 | throw "右键菜单的每个选项,都必须有它的事件处理函数";
68 | }
69 | // 追加右键菜单数据
70 | for (let i = 0; i < textArray.length; i++) {
71 | // 右键菜单对象, 添加名称
72 | const menuObj = {
73 | text: textArray[i],
74 | handler: handlerArray[i],
75 | id: i + 1
76 | };
77 | // 动态参数不为空则追加
78 | if (parameter != null) {
79 | menuObj.parameter = parameter;
80 | }
81 | menuList.push(menuObj);
82 | }
83 | // 鼠标点的坐标
84 | const oX = e.clientX;
85 | const oY = e.clientY;
86 | // 动态挂载组件,显示右键菜单
87 | menuVM = creatComp(rightMenu, {
88 | rightMenuStatus: "block",
89 | rightMenuTop: oY + "px",
90 | rightMenuLeft: oX + "px",
91 | rightMenuList: menuList
92 | });
93 | return false;
94 | };
95 | });
96 | }
97 | };
98 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // 强制css内联,不然会导致样式失效问题
3 | css: { extract: false },
4 | parallel: false
5 | };
6 |
--------------------------------------------------------------------------------
/webstorm.config.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const path = require("path");
4 |
5 | function resolve(dir) {
6 | return path.join(__dirname, ".", dir);
7 | }
8 |
9 | module.exports = {
10 | context: path.resolve(__dirname, "./"),
11 | resolve: {
12 | extensions: [".js", ".vue", ".json"],
13 | alias: {
14 | "@": resolve("src"),
15 | "@views": resolve("src/views"),
16 | "@comp": resolve("src/components"),
17 | "@core": resolve("src/core"),
18 | "@utils": resolve("src/utils")
19 | }
20 | }
21 | };
22 |
--------------------------------------------------------------------------------