MST

星途 面试题库

面试题:JavaScript 中在复杂页面结构下实现精准文档滚动监听及相关布局调整

假设页面有多层嵌套的滚动容器,且存在粘性布局元素,要求实现当滚动到特定区域时,粘性元素的布局和样式发生变化。请用 JavaScript 编写一个完整的解决方案,包括如何精准监听不同滚动容器的滚动事件,以及如何根据滚动位置进行复杂的布局和样式调整,同时要考虑不同浏览器的兼容性和性能优化。
26.4万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    .outer {
      height: 300px;
      overflow-y: scroll;
      border: 1px solid black;
    }

    .middle {
      height: 500px;
      overflow-y: scroll;
    }

    .inner {
      height: 800px;
    }

    .sticky {
      position: sticky;
      top: 20px;
      background-color: lightblue;
      padding: 10px;
    }
  </style>
  <title>Document</title>
</head>

<body>
  <div class="outer">
    <div class="middle">
      <div class="inner">
        <div class="sticky">Sticky Element</div>
        <p>Some content here...</p>
        <!-- 更多内容 -->
      </div>
    </div>
  </div>
  <script>
    // 获取滚动容器和粘性元素
    const outer = document.querySelector('.outer');
    const middle = document.querySelector('.middle');
    const sticky = document.querySelector('.sticky');

    // 监听外层滚动容器的滚动事件
    outer.addEventListener('scroll', throttle(() => {
      // 这里可以通过 outer.scrollTop 获取滚动位置
      const scrollTop = outer.scrollTop;
      if (scrollTop > 100) {
        // 当滚动到特定区域,修改粘性元素的样式
        sticky.style.backgroundColor = 'lightgreen';
        sticky.style.fontWeight = 'bold';
      } else {
        sticky.style.backgroundColor = 'lightblue';
        sticky.style.fontWeight = 'normal';
      }
    }, 200));

    // 监听中层滚动容器的滚动事件
    middle.addEventListener('scroll', throttle(() => {
      const scrollTop = middle.scrollTop;
      if (scrollTop > 200) {
        sticky.style.color ='red';
      } else {
        sticky.style.color = 'black';
      }
    }, 200));

    // 节流函数,用于性能优化
    function throttle(func, delay) {
      let timer = null;
      return function () {
        if (!timer) {
          func.apply(this, arguments);
          timer = setTimeout(() => {
            timer = null;
          }, delay);
        }
      };
    }

    // 兼容性处理
    if ('addEventListener' in window === false) {
      // 对于不支持addEventListener的旧浏览器,采用attachEvent
      outer.attachEvent('onscroll', throttle(() => {
        const scrollTop = outer.scrollTop;
        if (scrollTop > 100) {
          sticky.style.backgroundColor = 'lightgreen';
          sticky.style.fontWeight = 'bold';
        } else {
          sticky.style.backgroundColor = 'lightblue';
          sticky.style.fontWeight = 'normal';
        }
      }, 200));
      middle.attachEvent('onscroll', throttle(() => {
        const scrollTop = middle.scrollTop;
        if (scrollTop > 200) {
          sticky.style.color ='red';
        } else {
          sticky.style.color = 'black';
        }
      }, 200));
    }
  </script>
</body>

</html>
  1. HTML 结构:创建了多层嵌套的滚动容器 .outer.middle 和包含粘性元素 .sticky.inner 容器。
  2. CSS 样式:为滚动容器设置了滚动条和基本样式,为粘性元素设置了粘性定位和初始样式。
  3. JavaScript 部分
    • 获取滚动容器和粘性元素。
    • 使用 addEventListener 监听外层和中层滚动容器的 scroll 事件,并通过节流函数 throttle 进行性能优化,减少事件触发频率。
    • 在滚动事件回调中,根据不同滚动容器的 scrollTop 值来修改粘性元素的样式。
    • 编写了 throttle 函数,实现节流功能,避免频繁触发事件导致性能问题。
    • 在兼容性处理部分,对于不支持 addEventListener 的旧浏览器,采用 attachEvent 来绑定事件。