这是resize-observer-polyfill源码解读的第三章,在上一章的末尾,由于ResizeObserverController类内部没有调用自身内部的函数,并且controller作为单例参数被传入到了ResizeObserverSPI内。所以对于controller的操作,也都存在与SPI中。
先看看完整代码
import {
Map} from './shims/es6-collections.js';
import ResizeObservation from './ResizeObservation.js';
import ResizeObserverEntry from './ResizeObserverEntry.js';
import getWindowOf from './utils/getWindowOf.js';
export default class ResizeObserverSPI {
/**
* Collection of resize observations that have detected changes in dimensions
* of elements.
*
* @private {Array<ResizeObservation>}
*/
activeObservations_ = [];
/**
* Reference to the callback function.
*
* @private {ResizeObserverCallback}
*/
callback_;
/**
* Public ResizeObserver instance which will be passed to the callback
* function and used as a value of it's "this" binding.
*
* @private {ResizeObserver}
*/
callbackCtx_;
/**
* Reference to the associated ResizeObserverController.
*
* @private {ResizeObserverController}
*/
controller_;
/**
* Registry of the ResizeObservation instances.
*
* @private {Map<Element, ResizeObservation>}
*/
observations_ = new Map();
/**
* Creates a new instance of ResizeObserver.
*
* @param {ResizeObserverCallback} callback - Callback function that is invoked
* when one of the observed elements changes it's content dimensions.
* @param {ResizeObserverController} controller - Controller instance which
* is responsible for the updates of observer.
* @param {ResizeObserver} callbackCtx - Reference to the public
* ResizeObserver instance which will be passed to callback function.
*/
constructor(callback, controller, callbackCtx) {
if (typeof callback !== 'function') {
throw new TypeError('The callback provided as parameter 1 is not a function.');
}
this.callback_ = callback;
this.controller_ = controller;
this.callbackCtx_ = callbackCtx;
}
/**
* Starts observing provided element.
*
* @param {Element} target - Element to be observed.
* @returns {void}
*/
observe(target) {
if (!arguments.length) {
throw new TypeError('1 argument required, but only 0 present.');
}
// Do nothing if current environment doesn't have the Element interface.
if (typeof Element === 'undefined' || !(Element instanceof Object)) {
return;
}
if (!(target instanceof getWindowOf(target).Element)) {
throw new TypeError('parameter 1 is not of type "Element".');
}
const observations = this.observations_;
// Do nothing if element is already being observed.
if (observations.has(target)) {
return;
}
observations.set(target, new ResizeObservation(target));
this.controller_.addObserver(this);
// Force the update of observations.
this.controller_.refresh();
}
/**
* Stops observing provided element.
*
* @param {Element} target - Element to stop observing.
* @returns {void}
*/
unobserve(target) {
if (!arguments.length) {
throw new TypeError('1 argument required, but only 0 present.');
}
// Do nothing if current environment doesn't have the Element interface.
if (typeof Elemen