第三方包
addEventListener
源码: 参考 根据源码所示 支持传递自定义执行函数, 也可以使用默认的函数, 共有四个参数
**target**
: 监听事件的目标元素**eventType**
: 监听事件的类型**callback**
: 事件执行时的回调函数**options**
: 是否冒泡
因为监听事件的逻辑是依赖于 **dom**
节点的, 所以前期一定要获取到 React 中对应的真实 **DOM**
节点才可以执行, 再者在源码中出现了 unstable_batchedUpdates<**可以参考 [Batch Update 浅析](https://zhuanlan.zhihu.com/p/28532725)>(可以理解为是一个批量更新的钩子, 现在的问题是不稳定的钩子, 后续可能会被移除掉),返回的是一个包含有移除监听事件方法的对象**
import ReactDOM from 'react-dom';
export default function addEventListenerWrap(target, eventType, cb, option) {
/* 包含回调函数及批量更新钩子的处理 */
const callback = ReactDOM.unstable_batchedUpdates
? function run(e) {
ReactDOM.unstable_batchedUpdates(cb, e);
}
: cb;
// 对 Dom 节点进行事件监听注册
if (target.addEventListener) {
target.addEventListener(eventType, callback, option);
}
// 返回一个可以移除事件监听的处理方法
return {
remove: () => {
if (target.removeEventListener) {
target.removeEventListener(eventType, callback);
}
},
};
}
rc-animate
工具
getScroll
export function isWindow(obj: any) {
return obj !== null && obj !== undefined && obj === obj.window;
}
export default function getScroll(
target: HTMLElement | Window | Document | null,
top: boolean,
): number {
if (typeof window === 'undefined') {
return 0;
}
const method = top ? 'scrollTop' : 'scrollLeft';
let result = 0;
if (isWindow(target)) {
result = (target as Window)[top ? 'pageYOffset' : 'pageXOffset'];
} else if (target instanceof Document) {
result = target.documentElement[method];
} else if (target) {
result = (target as HTMLElement)[method];
}
if (target && !isWindow(target) && typeof result !== 'number') {
result = ((target as HTMLElement).ownerDocument || (target as Document)).documentElement[
method
];
}
return result;
}