util.js
/**
* 获取给定元素的 CSS 计算属性
* @function
* @ignore
* @argument {Eement} element 给定的元素
* @argument {String} property 属性
*/
export function getStyleComputedProperty(element, property) {
// 注:这里会访问 DOM
var css = window.getComputedStyle(element, null);
return css[property];
}
/**
* 返回给定元素用来计算滚动的父元素
* @function
* @ignore
* @argument {Element} element
* @returns {Element} scroll parent
*/
export function getScrollParent(element) {
var parent = element.parentNode;
if (!parent) { // 没有父级
return element;
}
if (parent === window.document) {
// Firefox 会将 scrollTop的判断放置的 `documentElement` 而非 `body` 上
// 我们将判断二者谁大于0来返回正确的元素
if (window.document.body.scrollTop) {
return window.document.body;
} else {
return window.document.documentElement;
}
}
// Firefox 要求我们也要检查 `-x` 以及 `-y`
if (
['scroll', 'auto'].indexOf(getStyleComputedProperty(parent, 'overflow')) !== -1 ||
['scroll', 'auto'].indexOf(getStyleComputedProperty(parent, 'overflow-x')) !== -1 ||
['scroll', 'auto'].indexOf(getStyleComputedProperty(parent, 'overflow-y')) !== -1
) {
// 如果检测到的 scrollParent 是 body,我们将对其父元素做一次额外的检测
// 这样在 Chrome 系的浏览器中会得到 body,其他情况下会得到 documentElement
// 修复 issue #65
return parent;
}
return getScrollParent(element.parentNode);
}
dropdown.vue
directives: {
clickoutside: {
bind(el, binding, vnode) {
function resetRect() {
// 修正dropdown坐标
vnode.context.rect = el.getBoundingClientRect();
console.log('vnode.context.rect>>>>', vnode.context.rect)
}
el.__vueScroll__ = resetRect;
document.addEventListener('scroll', el.__vueScroll__);
},
inserted(el){
let target = getScrollParent( el );
target.addEventListener('scroll', el.__vueScroll__);
},
unbind(el, binding) {
let target = getScrollParent( el );
target.removeEventListener('scroll', el.__vueScroll__);
document.removeEventListener('scroll', el.__vueScroll__);
delete el.__vueScroll__;
}
}
}