赞
踩
-
-
- this.options = {
- ListenEvents: listenEvents || DEFAULT_EVENTS,
- }
- /*
- * add or remove eventlistener
- * @param {DOM} el DOM or Window
- * @param {boolean} start flag
- * @return
- */
- initListen(el, start) {
- this.options.ListenEvents.forEach((evt) =>
- (start ? on : off)(el, evt, this.lazyLoadHandler)
- );
- }
- 复制代码
8.4.1 on、off 监听事件,移除事件
- export function on(el, type, func) {
- el.addEventListener(type, func, {
- capture: false,
- passive: true,
- });
- }
- 复制代码
- // vant/packages/vant/src/lazyload/vue-lazyload/util.js
- export function off(el, type, func) {
- el.removeEventListener(type, func, false);
- }
- 复制代码
- /**
- * init IntersectionObserver
- * set mode to observer
- * @return
- */
- initIntersectionObserver() {
- if (!hasIntersectionObserver) {
- return;
- }
-
- this.observer = new IntersectionObserver(
- this.observerHandler.bind(this),
- this.options.observerOptions
- );
-
- if (this.listeners.length) {
- this.listeners.forEach((listener) => {
- this.observer.observe(listener.el);
- });
- }
- }
- 复制代码
mdn 文档:IntersectionObserverEntry
- /**
- * init IntersectionObserver
- * @return
- */
- observerHandler(entries) {
- entries.forEach((entry) => {
- if (entry.isIntersecting) {
- this.listeners.forEach((listener) => {
- // 如果加载完成了,就移除监听
- if (listener.el === entry.target) {
- if (listener.state.loaded)
- return this.observer.unobserve(listener.el);
- listener.load();
- }
- });
- }
- });
- }
- 复制代码
- /*
- * add lazy component to queue
- * @param {Vue} vm lazy component instance
- * @return
- */
- addLazyBox(vm) {
- this.listeners.push(vm);
- // 浏览器环境
- if (inBrowser) {
- // 把
- this.addListenerTarget(window);
- // 如果是监听 observer 模式,监听 new IntersectionObserver().observe(vm.el)
- this.observer && this.observer.observe(vm.el);
- if (vm.$el && vm.$el.parentNode) {
- // 加入父级
- this.addListenerTarget(vm.$el.parentNode);
- }
- }
- }
- 复制代码
- /*
- * remove lazy components form list
- * @param {Vue} vm Vue instance
- * @return
- */
- removeComponent(vm) {
- if (!vm) return;
- remove(this.listeners, vm);
- this.observer && this.observer.unobserve(vm.el);
- // 移除父级
- if (vm.$parent && vm.$el.parentNode) {
- this.removeListenerTarget(vm.$el.parentNode);
- }
- // 移除 window 元素
- this.removeListenerTarget(window);
- }
- 复制代码
比如 window 等。
- /*
- * add listener target
- * @param {DOM} el listener target
- * @return
- */
- addListenerTarget(el) {
- if (!el) return;
- let target = this.targets.find((target) => target.el === el);
- if (!target) {
- target = {
- el,
- id: ++this.targetIndex,
- childrenCount: 1,
- listened: true,
- };
- this.mode === modeType.event && this.initListen(target.el, true);
- this.targets.push(target);
- } else {
- target.childrenCount++;
- }
- return this.targetIndex;
- }
- 复制代码
- /*
- * remove listener target or reduce target childrenCount
- * @param {DOM} el or window
- * @return
- */
- removeListenerTarget(el) {
- this.targets.forEach((target, index) => {
- if (target.el === el) {
- target.childrenCount--;
- if (!target.childrenCount) {
- this.initListen(target.el, false);
- this.targets.splice(index, 1);
- target = null;
- }
- }
- });
- }
- 复制代码
大致流程:
- 1. 初始化在元素(比如是 window,但不一定是 window)添加监听滚动和其他相关事件
- 2. 使用 Element.getBoundingClientRect API 获取元素的大小及其相对于视口的位置,判断是否进入可视化区
- 3. 进入可视区触发 load 事件,将图片设置 src 真实的图片路径,从而自动加载图片
- 4. 离开销毁监听的事件、和移除绑定事件的元素
- 复制代码
主要是第二步用 IntersectionObserver API。
- // 把 Vue 实例对象 this 添加到 lazy 实例中
- lazyManager.addLazyBox(this);
- // 执行 lazyLoaderHandler 函数(发现节点(元素)在视口 checkInView,触发 load 事件)
- lazyManager.lazyLoadHandler();
- // 移除组件
- lazyManager.removeComponent(this);
- 复制代码
在 load 事件中,调用 loadImageAsync
函数。
- const image = new Image();
- image.src = xxx;
- image.onload = () => {}
- image.onerror = () => {}
- 复制代码
行文至此,我们就算分析完了 lazyload 组件。
其中,有很多细节处理值得我们学习。 比如:
scroll
事件,还有'scroll','wheel','mousewheel','resize','animationend','transitionend','touchmove'
install
函数主要有以下实现:
但限于篇幅原因,组件源码还有指令部分没有分析。 感兴趣的小伙伴可以自行分析学习。
如果看完有收获,欢迎点赞、评论、分享支持。你的支持和肯定,是我写作的动力。
最后可以持续关注我@若川。我会写一个组件库源码系列专栏,欢迎大家关注。
我倾力持续组织了一年每周大家一起学习200行左右的源码共读活动,感兴趣的可以点此扫码加我微信 ruochuan12 参与。
作者:若川
链接:https://juejin.cn/post/7171227417246171149
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。