阅读element-ui源码之ResizeObserver使用

1.ResizeObserver

阅读tabs标签页源码时,发现了这个api。于是,我查了下MDN。

  • 可以监听任意DOM元素内容区域的变化。这里的变化包括但不限于:
    (1)某个节点的出现和隐藏。(2)某个节点的大小变化。
  • 和resize api相比的优点:
    众所周知window.resize事件能帮我们监听窗口大小的变化。但是reize事件会在一秒内触发将近60次,所以很容易在改变窗口大小时导致性能问题。换句话说,window.resize事件通常是浪费的,因为它会监听每个元素的大小变化(只有window对象才有resize事件)。ResizeObserver的优点就不言而喻了。
  • 具体的用法就不说了。可以去MDN上查找。下面重点说下,element-ui是如何使用的?

2.element-ui中的使用

  • 首先,ResizeObserver这个api是有兼容性问题的。element-ui引入了第三方库:
import ResizeObserver from 'resize-observer-polyfill';
  • 接着,它采用了观察者模式,来处理元素尺寸变化逻辑。
// 判断是否在浏览器环境中,还是在node中
const isServer = typeof window === 'undefined';

/* istanbul ignore next */
const resizeHandler = function(entries) {
  for (let entry of entries) {
    // entry.target通过这个访问监听的DOM对象,然后,这个对象上有__resizeListeners__属性。遍历存储的监听回调
    const listeners = entry.target.__resizeListeners__ || [];
    if (listeners.length) {
      listeners.forEach(fn => {
        fn();
      });
    }
  }
};

/* istanbul ignore next */
// 接受DOM元素和方法
export const addResizeListener = function(element, fn) {
  if (isServer) return;
  if (!element.__resizeListeners__) {
    // 在DOM元素对象上,设置__resizeListeners__属性,存储监听器(回调函数)。
    element.__resizeListeners__ = [];
    // ResizeObserver:MDN上解释可以监听DOM元素的变化(什么变化呢?位置变化和大小变化)
    element.__ro__ = new ResizeObserver(resizeHandler);
    element.__ro__.observe(element);// 这里观察主体是DOM对象。(本质就是观察一个对象)
  }
  element.__resizeListeners__.push(fn);
};

/* istanbul ignore next */
export const removeResizeListener = function(element, fn) {
  if (!element || !element.__resizeListeners__) return; // 先判断下
  element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
  if (!element.__resizeListeners__.length) {
    // 取消element.__ro__观察者身上所有的元素的观察
    element.__ro__.disconnect();
  }
};

你可能感兴趣的:(element-UI源码,ui,javascript,vue.js)