Skip to content

Latest commit

 

History

History
105 lines (95 loc) · 2.64 KB

lazyLoad.md

File metadata and controls

105 lines (95 loc) · 2.64 KB

v-LazyLoad

?> 实现一个图片懒加载指令,只加载浏览器可见区域的图片

图片懒加载的原理主要是判断当前图片是否到了可视区域这一核心逻辑实现的

拿到所有的图片 Dom ,遍历每个图片判断当前图片是否到了可视区范围内

如果到了就设置图片的 src 属性,否则显示默认图片

!> 图片懒加载有两种方式可以实现,一是绑定 srcoll 事件进行监听,二是使用 IntersectionObserver 判断图片是否到了可视区域,但是有浏览器兼容性问题。

!> 解决方案:判断浏览器是否支持 IntersectionObserver API,如果支持就使用 IntersectionObserver 实现懒加载,否则则使用 srcoll 事件监听 + 节流的方法实现

	const LazyLoad = {
		// install方法
		install(Vue, options) {
			const defaultSrc = options.default
			Vue.directive('lazy', {
				bind(el, binding) {
					LazyLoad.init(el, binding.value, defaultSrc)
				},
				inserted(el) {
					if (IntersectionObserver) {
						LazyLoad.observe(el)
					} else {
						LazyLoad.listenerScroll(el)
					}
				},
			})
		},
		// 初始化
		init(el, val, def) {
			el.setAttribute('data-src', val)
			el.setAttribute('src', def)
		},
		// 利用IntersectionObserver监听el
		observe(el) {
			var io = new IntersectionObserver((entries) => {
				const realSrc = el.dataset.src
				if (entries[0].isIntersecting) {
					if (realSrc) {
						el.src = realSrc
						el.removeAttribute('data-src')
					}
				}
			})
			io.observe(el)
		},
		// 监听scroll事件
		listenerScroll(el) {
			const handler = LazyLoad.throttle(LazyLoad.load, 300)
			LazyLoad.load(el)
			window.addEventListener('scroll', () => {
				handler(el)
			})
		},
		// 加载真实图片
		load(el) {
			const windowHeight = document.documentElement.clientHeight
			const elTop = el.getBoundingClientRect().top
			const elBtm = el.getBoundingClientRect().bottom
			const realSrc = el.dataset.src
			if (elTop - windowHeight < 0 && elBtm > 0) {
				if (realSrc) {
					el.src = realSrc
					el.removeAttribute('data-src')
				}
			}
		},
		// 节流
		throttle(fn, delay) {
			let timer
			let prevTime
			return function (...args) {
				const currTime = Date.now()
				const context = this
				if (!prevTime) prevTime = currTime
				clearTimeout(timer)
			
				if (currTime - prevTime > delay) {
					prevTime = currTime
					fn.apply(context, args)
					clearTimeout(timer)
					return
				}
			
				timer = setTimeout(function () {
					prevTime = Date.now()
					timer = null
					fn.apply(context, args)
				}, delay)
			}
		},
	}
	
	export default LazyLoad

示例

	<img v-LazyLoad="xxx.jpg" />