UNPKG

1.89 kBJavaScriptView Raw
1import Vue from 'vue';
2import { on } from 'element-ui/src/utils/dom';
3
4const nodeList = [];
5const ctx = '@@clickoutsideContext';
6
7let startClick;
8let seed = 0;
9
10!Vue.prototype.$isServer && on(document, 'mousedown', e => (startClick = e));
11
12!Vue.prototype.$isServer && on(document, 'mouseup', e => {
13 nodeList.forEach(node => node[ctx].documentHandler(e, startClick));
14});
15
16function createDocumentHandler(el, binding, vnode) {
17 return function(mouseup = {}, mousedown = {}) {
18 if (!vnode ||
19 !vnode.context ||
20 !mouseup.target ||
21 !mousedown.target ||
22 el.contains(mouseup.target) ||
23 el.contains(mousedown.target) ||
24 el === mouseup.target ||
25 (vnode.context.popperElm &&
26 (vnode.context.popperElm.contains(mouseup.target) ||
27 vnode.context.popperElm.contains(mousedown.target)))) return;
28
29 if (binding.expression &&
30 el[ctx].methodName &&
31 vnode.context[el[ctx].methodName]) {
32 vnode.context[el[ctx].methodName]();
33 } else {
34 el[ctx].bindingFn && el[ctx].bindingFn();
35 }
36 };
37}
38
39/**
40 * v-clickoutside
41 * @desc 点击元素外面才会触发的事件
42 * @example
43 * ```vue
44 * <div v-element-clickoutside="handleClose">
45 * ```
46 */
47export default {
48 bind(el, binding, vnode) {
49 nodeList.push(el);
50 const id = seed++;
51 el[ctx] = {
52 id,
53 documentHandler: createDocumentHandler(el, binding, vnode),
54 methodName: binding.expression,
55 bindingFn: binding.value
56 };
57 },
58
59 update(el, binding, vnode) {
60 el[ctx].documentHandler = createDocumentHandler(el, binding, vnode);
61 el[ctx].methodName = binding.expression;
62 el[ctx].bindingFn = binding.value;
63 },
64
65 unbind(el) {
66 let len = nodeList.length;
67
68 for (let i = 0; i < len; i++) {
69 if (nodeList[i][ctx].id === el[ctx].id) {
70 nodeList.splice(i, 1);
71 break;
72 }
73 }
74 delete el[ctx];
75 }
76};