Skip to content

Commit 1a0d812

Browse files
committed
修复移动端单击外部不能折叠菜单
1 parent a8c730e commit 1a0d812

File tree

1 file changed

+67
-15
lines changed

1 file changed

+67
-15
lines changed

src/directives/clickoutside.js

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,71 @@
1+
const isTouch =
2+
typeof window !== "undefined" && ("ontouchstart" in window || navigator.msMaxTouchPoints > 0);
3+
const events = isTouch ? ["touchstart", "click"] : ["click"];
4+
5+
const instances = [];
6+
7+
function processDirectiveArguments(bindingValue) {
8+
const isFunction = typeof bindingValue === "function";
9+
if (!isFunction && typeof bindingValue !== "object") {
10+
throw new Error("v-click-outside: Binding value must be a function or an object");
11+
}
12+
13+
return {
14+
handler: isFunction ? bindingValue : bindingValue.handler,
15+
middleware: bindingValue.middleware || (isClickOutside => isClickOutside),
16+
events: bindingValue.events || events
17+
};
18+
}
19+
20+
function onEvent({ el, event, handler, middleware }) {
21+
const isClickOutside = event.target !== el && !el.contains(event.target);
22+
if (!isClickOutside) {
23+
return;
24+
}
25+
if (middleware(event, el)) {
26+
handler(event, el);
27+
}
28+
}
29+
130
export default {
2-
bind(el, binding) {
3-
function documentHandler(e) {
4-
if (el.contains(e.target)) {
5-
return false;
6-
}
7-
if (binding.expression) {
8-
binding.value(e);
9-
}
10-
}
11-
el.__vueClickOutside__ = documentHandler;
12-
document.addEventListener("click", documentHandler);
31+
bind(el, { value }) {
32+
const { handler, middleware, events } = processDirectiveArguments(value);
33+
34+
const instance = {
35+
el,
36+
eventHandlers: events.map(eventName => ({
37+
event: eventName,
38+
handler: event => onEvent({ event, el, handler, middleware })
39+
}))
40+
};
41+
42+
instance.eventHandlers.forEach(({ event, handler }) =>
43+
document.addEventListener(event, handler)
44+
);
45+
instances.push(instance);
46+
},
47+
update(el, { value }) {
48+
const { handler, middleware, events } = processDirectiveArguments(value);
49+
const instance = instances.find(instance => instance.el === el);
50+
51+
instance.eventHandlers.forEach(({ event, handler }) =>
52+
document.removeEventListener(event, handler)
53+
);
54+
55+
instance.eventHandlers = events.map(eventName => ({
56+
event: eventName,
57+
handler: event => onEvent({ event, el, handler, middleware })
58+
}));
59+
60+
instance.eventHandlers.forEach(({ event, handler }) =>
61+
document.addEventListener(event, handler)
62+
);
1363
},
14-
update() {},
1564
unbind(el) {
16-
document.removeEventListener("click", el.__vueClickOutside__);
17-
delete el.__vueClickOutside__;
18-
}
65+
const instance = instances.find(instance => instance.el === el);
66+
instance.eventHandlers.forEach(({ event, handler }) =>
67+
document.removeEventListener(event, handler)
68+
);
69+
},
70+
instances
1971
};

0 commit comments

Comments
 (0)