自己封装的vue组件时,有时会用的到, 基于此,直接复制粘贴拿来。
工具函数准备
export const on = (function () {
if (document.addEventListener) {
return function (element, event, handler) {
if (element && event && handler) {
element.addEventListener(event, handler, false);
}
}
} else {
return function (element, event, handler) {
if (element && event && handler) {
element.attachEvent('on' + event, handler);
}
};
}
})()
直接开撸
const nodeList = []
const ctx = '$@clickoutdiseVode'
let startClick
let seed = 0
on(document, 'mousedown', e => { startClick = e })
on(document, 'mouseup', e => { nodeList.forEach(node => { node[ctx].documentHandler(e, startClick) }) })
export default {
bind (el, binding, vnode) {
nodeList.push(el);
const id = seed++;
const documentHandler = function (mouseup = {}, mousedown = {}) {
if (!vnode.context || !mouseup.target || !mousedown.target || el.contains(mouseup.target) || el.contains(mousedown.target) || el === mouseup.target || (vnode.context.popperElm && (vnode.context.popperElm.contains(mouseup.target) || vnode.context.popperElm.contains(mousedown.target)))) return;
if (binding.expression && el[ctx].methodName && vnode.context[el[ctx].methodName]) {
vnode.context[el[ctx].methodName]();
} else {
el[ctx].bindingFn && el[ctx].bindingFn();
}
};
el[ctx] = {
id,
documentHandler,
methodName: binding.expression,
bindingFn: binding.value
};
},
update(el, binding) {
el[ctx].methodName = binding.expression;
el[ctx].bindingFn = binding.value;
},
unbind(el) {
let len = nodeList.length;
for (let i = 0; i < len; i++) {
if (nodeList[i][ctx].id === el[ctx].id) {
nodeList.splice(i, 1);
break;
}
}
}
}