wingmeng / front-end-quiz

前端小测试答题收集
0 stars 0 forks source link

DOM基础测试27:返回顶部 #3

Open wingmeng opened 5 years ago

wingmeng commented 5 years ago

题目:

image


我的答案:

第 1 题和第 2 题,两大问题,一个对策。已封装成组件,只需为构造函数传入需要“返回顶部”功能的容器元素即可,默认为 body 元素。

在线演示

.back-top {
  position: fixed;
  margin-top: -15px;
  margin-left: -15px;
  transform: translate(-100%, -100%);
  white-space: nowrap;
}
/**
 * 返回顶部
 * @descr: 给定一个容器,当滚动高度超出1倍的容器高度,显示返回顶部,否则隐藏
 * @param {object HTMLElement} [elm] - HTML元素,可选,默认为 body 元素
 */
function ScrollBackTop(elm) {
  var that = this;
  var timer = null;

  this.elm = elm || document;
  this.elmBox = elm || document.documentElement;
  this.render();

  // 监听容器 scroll 事件
  this.elm.addEventListener('scroll', function() {
    clearTimeout(timer);
    timer = setTimeout(function() {
      that.scrolling();
    }, 20);
  }, false);

  // 监听视窗尺寸改变
  window.addEventListener('resize', function() {
    clearTimeout(timer);
    timer = setTimeout(function() {
      that.scrolling();
    }, 20);
  }, false);
}

// 生成按钮
ScrollBackTop.prototype.render = function() {
  var that = this;
  var btn = document.createElement('a');
  var text = document.createTextNode('返回顶部↑');

  btn.className = 'back-top';
  btn.href = '#';
  btn.hidden = true;

  // 监听点击
  btn.addEventListener('click', function(event) {
    if (that.elm === document) {
      window.scrollTo(0, 0);  // 兼容移动端
    } else {
      that.elmBox.scrollTop = 0;
    }

    event.preventDefault();
    return false;
  }, false);

  btn.appendChild(text);
  (this.elm === document ? document.body : this.elm).appendChild(btn);

  this.btn = btn;
}

ScrollBackTop.prototype.scrolling = function() {
  var elmBox = this.elmBox;
  var scroll_y = this.elm === document ? window.pageYOffset : elmBox.scrollTop;
  var offset_x = elmBox.offsetLeft;
  var offset_y = elmBox.offsetTop;
  var x = elmBox.clientWidth;
  var y = elmBox.clientHeight;

  if (scroll_y >= y) {
    this.btn.hidden = false;

    // 按钮的显示位置
    this.btn.style.top = offset_y + y + 'px';
    this.btn.style.left = offset_x + x + 'px';
  } else {
    this.btn.hidden = true;
  }
}

new ScrollBackTop();  // 整个文档返回顶部的场景
new ScrollBackTop(document.getElementById('divBox'));  // 某个 div 容器的场景
wingmeng commented 5 years ago

自我评分:良好

优秀、良好、一般、差劲

不足之处:

  1. 代码逻辑稍显啰嗦

学习收获:

  1. getBoundingClientRect 方法;
  2. 加深了对 clientWidthoffsetWidthscrollWidth 的理解;
  3. 移动端和 PC 端在页面滚动事件绑定上的区别。