用js实现offset方法

2020-04-27  本文已影响0人  _BuzzLy

本来前段时间在整理关于vue组件封装、bind实现、promise实现的文章。但是由于篇幅有点大,并且笔记有些久远好多东西还要再更新下,所以就推迟了。就简单整理下最近自己写过的代码中比较有代表性的例子。

如何用js实现jq中的offset方法。

JQuery中的offset方法是获取当前元素上边框到document顶部距离的。
需要实现offset可以借助js中的offsetTop、offsetLeft。
js 的 offsetTop、offsetLeft 是用来访问一个 DOM 节点上边框相对其本身最近、且position值为非static的祖先元素的垂直和水平偏移量。
最后再借用递归就可以轻松实现了,代码如下

const offset = ele => {
   let position
   let result = {
        top: 0,
        left: 0
    }

    const getOffset = (node, init) => {
        // 如果不是元素节点,则直接返回。nodeType=1为元素节点,
        if (node.nodeType !== 1) {
            return
        }

        // window.getComputedStyle获取元素的所有样式
        position = window.getComputedStyle(node)['position']

        // 如不是首次计算,并且position为static,继续计算父级
        if (typeof (init) === 'undefined' && position === 'static') {
            getOffset(node.parentNode)
            return
        }

        // 减去node.scrollTop是因为,如果元素在一个带有滚动条的父元素内,则offsetTop会获取整个高度
        // 如果滚动条不为0则需要减去已滚动的部分。
        result.top += node.offsetTop - node.scrollTop
        result.left += node.offsetLeft - node.scrollLeft

        if (position === 'fixed') {
            return
        }
        
        // 递归调用
        getOffset(node.parentNode)
    }

    // 当前 DOM 节点的 display === 'none' 时, 直接返回 {top: 0, left: 0}
    if (window.getComputedStyle(ele)['display'] === 'none') {
        return result
    }

    getOffset(ele, true)
    return result
}

代码非常简单易懂,但是在平时开发中很少会遇到这样的问题。不过在面试中这又是一个高频的考点,非常考验js基本功。实现方法有很多,在这就列举一种容易理解的,有兴趣的小伙伴可以自己尝试其他方式实现。

上一篇下一篇

猜你喜欢

热点阅读