javascript - 没有 jQuery 的 Vue.js 中带有固定标题的粘性侧边栏

标签 javascript jquery html css vuejs2

正在关注 this回答类似问题Make position: fixed behavior like sticky (for Vue2) ,我已尝试在我的应用程序中实现它。

该解决方案有点问题(在某些情况下它表现得很奇怪,尤其是在打开其他选项卡并返回时),所以我决定使用 jQuery 实现它并且它按预期工作。

这是工作示例:

<template>
    <div>
        <div class="recap">
            <div class="inner" :style="recapStyle">
            </div>
        </div>
    </div>
</template>
<script>
export default {
    name: 'ProductRecap',
    data() {
        return {
            scrollY: null,
            top: null,
            bottom: null,
            marginTop: 40,
            recapStyle: {},
        };
    },
    methods: {
        updatePosition(scroll) {
            // using jQuery to calculate amount
            const offset = $(this.$el).offset().top;
            const scrollAmount = offset - scroll;
            const rectHeight = $(this.$el).find('.inner').outerHeight();
            if (scrollAmount < this.top) {
                let updatedTop = scroll - offset + this.top;
                if ((scroll + rectHeight) < this.bottom) {
                    this.prevScroll = updatedTop;
                } else {
                    updatedTop = this.prevScroll;
                }
                this.$set(this.recapStyle, 'top', `${updatedTop}px`);
            } else {
                this.$delete(this.recapStyle, 'top');
            }
        },
    },
    watch: {
        scrollY(scrollUpdate) {
            // call `updatePosition` on scroll
            this.updatePosition(scrollUpdate);
        },
    },
    mounted() {
        // calculate header size (position: fixed) and add a fixed offset
        this.top = $('#main-header').outerHeight() + this.marginTop;
        // calculate height of the document (without the footer)
        this.bottom = document.querySelector('.global-container').offsetHeight;
        // update scrollY position
        window.addEventListener('scroll', _.throttle(() => {
            this.scrollY = Math.round(window.scrollY);
        }, 20, { leading: true }));
    },
};
</script>

但是我想找到一个不使用 jQuery 来计算偏移量的解决方案,所以我前往 You Might Not Need jQuery ,但如果我只是将 offset 部分替换为建议的部分,它仍然有点问题。

$(el).offset();

应该变成:

var rect = el.getBoundingClientRect();

{
  top: rect.top + document.body.scrollTop,
  left: rect.left + document.body.scrollLeft
}

所以我替换了这一行:

const offset = $(this.$el).offset().top;

与:

const rect = this.$el.getBoundingClientRect();
const offset = rect.top + document.body.scrollTop;

但是侧边栏与固定标题的距离随着滚动而增加:谁能解释一下如何修复它?

这是一个工作 fiddle (稍微简化):Fiddle

最佳答案

简短的回答是使用这两行(第一行是你的):

  const rect = this.$el.getBoundingClientRect();
  const offset = rect.top + window.pageYOffset;

较长的答案当然包括实现此结果的思考过程。我跑了

  console.log($(this.$el).offset + "");

在相关地方的 fiddle 上查看偏移功能的实现方式并得到:

function( options ) {

        // Preserve chaining for setter
        if ( arguments.length ) {
            return options === undefined ?
                this :
                this.each( function( i ) {
                    jQuery.offset.setOffset( this, options, i );
                } );
        }

        var rect, win,
            elem = this[ 0 ];

        if ( !elem ) {
            return;
        }

        // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
        // Support: IE <=11+
        // Running getBoundingClientRect on a
        // disconnected node in IE throws an error
        if ( !elem.getClientRects().length ) {
            return { top: 0, left: 0 };
        }

        // Get document-relative position by adding viewport scroll to viewport-relative gBCR
        rect = elem.getBoundingClientRect();
        win = elem.ownerDocument.defaultView;
        return {
            top: rect.top + win.pageYOffset,
            left: rect.left + win.pageXOffset
        };
    }

解决方案的灵感来自于这一行:

            top: rect.top + win.pageYOffset,

关于javascript - 没有 jQuery 的 Vue.js 中带有固定标题的粘性侧边栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57463159/

相关文章:

javascript - 使用 HTML 创建图表

javascript - 如何在客户端 javascript 中使用 node.js 缓冲区库

jquery - 标签和输入字段之间的点

jquery - 浏览器警报样式

javascript - 如何将信息输入到一系列表格中并显示该信息?

html - 当父级使用 flex 且元素没有内容时,Flex 子级在容器上增长

javascript - 最新的dom源代码

javascript - JSON 类似 Javascript 结构

javascript - console.log() 显示变量值实际变化前的变化值

jquery - 在每个 li 之后在 div 上 Accordion