700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 图片懒加载及Vue自定义图片懒加载指令

图片懒加载及Vue自定义图片懒加载指令

时间:2022-01-19 22:57:44

相关推荐

图片懒加载及Vue自定义图片懒加载指令

文章目录

监听滚动的方式IntersectionObserver方式自定义图片懒加载vue指令1自定义图片懒加载vue指令2lazyLoadImage.jsmain.js中注册指令组件中使用

学习链接:

前端必会的图片懒加载

vue自定义指令实现图片懒加载

监听滚动的方式

img的src先都用一张默认的图片,data-src属性为真实图片地址当图片出现在可视区范围内时,把src属性换成data-src属性,就完成了缺点:一当发生滚动事件时,就发生了大量的循环和判断操作判断图片是否可视区里补充一点:当把img的src从默认的图片换成真实的图片url后,在真实图片未加载完成前,还会一直是默认图片

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {padding: 0;margin: 0;}img {width: 200px;height: 200px;object-fit: cover;}</style><script>window.onload = function () {window.addEventListener('scroll', loadImg)function loadImg() {console.log('-----'); // 每一次滚动都会执行,可能滚动条只滚动了一小段距离,但这个函数执行了很多次let imgs = document.querySelectorAll('img')// console.dir(imgs[0].getAttribute('data-src'));// console.dir(imgs[0].getAttribute('src'));for (let i = 0; i < imgs.length; i++) {if(imgs[i].getBoundingClientRect().top < window.innerHeight - 200) {// 也可以这样判断:imgs[i].offsetTop <= window.scrollY + window.innerHeight - 200imgs[i].setAttribute('src', imgs[i].getAttribute('data-src'))}}}loadImg() // 刚开始的时候,也要加载一次看看有没有图片就正好满足显示条件}</script></head><body><img src="./img/img0.jpg" data-src="./img/post1.jpg"><img src="./img/img0.jpg" data-src="./img/post2.jpg"><img src="./img/img0.jpg" data-src="./img/post3.jpg"><img src="./img/img0.jpg" data-src="./img/post4.jpg"><img src="./img/img0.jpg" data-src="./img/post5.jpg"><img src="./img/img0.jpg" data-src="./img/post6.jpg"></body></html>

IntersectionObserver方式

IntersectionObserver是浏览器原生提供的构造函数使用IntersectionObserver的observe方法,来观察某个元素使用IntersectionObserver的unobserve方法,来取消观察某个元素页面一加载的时候,就会返回所有被观察的元素它们的情况,注意是所有。此后,当某个元素出现在可视区时(从不在可视区到在可视区那个时刻),或者某个离开时可视区时(从在可视区到不在可视区的那个时刻),都会触发回调函数,回调函数传过来的参数就会告诉使用者哪些元素正在离开可视区,哪些元素正在进入可视区。除了回调函数这个参数外,还可以指定一个配置对象,配置对象中可以配置threshold,它表示目标元素与根元素的交叉比例,可以是单一的 number 也可以是 number 数组,比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。详细解释:IntersectionObserver API详解

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {padding: 0;margin: 0;}img {width: 200px;height: 200px;object-fit: cover;}</style><script>window.onload = function () {function callback(entries) {console.log(entries); /* [IntersectionObserverEntry,..] */for(let i of entries) {if(i.isIntersecting) {/* 当元素出现在可视窗口时 */let img = i.targetimg.setAttribute('src',img.getAttribute('data-src'))observer.unobserve(img) /* 已经看见的图片, 取消观察 */}}}/* IntersectionObserver是浏览器原生提供的构造函数 */const observer = new IntersectionObserver(callback);let imgs = document.querySelectorAll('img')/* 可以为每一张图片绑定一个观察器 */for (let i of imgs) {observer.observe(i);}}</script></head><body><img src="./img/img0.jpg" data-src="./img/post1.jpg"><img src="./img/img0.jpg" data-src="./img/post2.jpg"><img src="./img/img0.jpg" data-src="./img/post3.jpg"><img src="./img/img0.jpg" data-src="./img/post4.jpg"><img src="./img/img0.jpg" data-src="./img/post5.jpg"><img src="./img/img0.jpg" data-src="./img/post6.jpg"></body></html>

自定义图片懒加载vue指令1

<style>img {width: 200px;height: 200px;object-fit: cover;display: block;}</style><template><div>LazyImg<br/><img src="@/assets/post1.jpg" v-lazy alt=""><img src="@/assets/post2.jpg" v-lazy alt=""><img src="@/assets/post3.jpg" v-lazy alt=""><img src="@/assets/post4.jpg" v-lazy alt=""><img src="@/assets/post5.jpg" v-lazy alt=""><img src="@/assets/post6.jpg" v-lazy alt=""></div></template><script>import img0 from '@/assets/img0.jpg'console.log(img0);console.log(require('@/assets/img0.jpg'));export default {name: 'lazyImg',directives: {lazy: {bind(el,binding) {el.setAttribute("data-src",el.getAttribute("src"))el.setAttribute("src", img0)let observer = new IntersectionObserver(entries=>{for(let i of entries) {if(i.isIntersecting) {el.setAttribute('src',el.getAttribute("data-src") )observer.unobserve(el)}}})observer.observe(el)}}},components: {}}</script>

自定义图片懒加载vue指令2

lazyLoadImage.js

const lazyLoadImage = defaultImage => {let windowHeight = document.documentElement.clientHeight || document.body.clientHeight//可视区域高function throttle(fn, delay) {//节流let timeout = nullreturn (...args) => {if (timeout) returntimeout = setTimeout(() => {fn.apply(this, args)timeout = null}, delay);}}function loadImage(el) {//加载图片return () => {let top = el.getBoundingClientRect().toplet bottom = el.getBoundingClientRect().bottomif (top - windowHeight < 0 && bottom > 0&&el.hasAttribute('data-src')) {//图片出现在可视区域内开始加载图片el.src = el.getAttribute('data-src')el.removeAttribute('data-src')}}}return {bind(el, binding) {console.log(defaultImage);let realSrc = el.srcel.src = defaultImageel.setAttribute('data-src', realSrc) },inserted(el) {loadImage(el)()//显示初始(首屏)图片window.addEventListener('scroll', throttle(loadImage(el), 500))//每滚动500毫秒加载一次图片}}}const install = {install(vue, defaultImage) {//v-lazyvue.directive('lazy1', lazyLoadImage(defaultImage))}}export default install

main.js中注册指令

import Vue from 'vue'import App from './App.vue'import router from './router'import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';import '@/assets/css/base.css'import '@/assets/iconfont/iconfont.css'import 'animate.css'Vue.config.productionTip = falseVue.use(ElementUI);import lazyLoadImage from './utils/lazyLoadImage'const defaultImage=require('@/assets/img0.jpg')//默认占位图片Vue.use(lazyLoadImage,defaultImage)new Vue({router,render: h => h(App)}).$mount('#app')

组件中使用

<style>img {width: 200px;height: 200px;object-fit: cover;display: block;}</style><template><div>LazyImg<br/><img src="@/assets/post1.jpg" v-lazy1 alt=""><img src="@/assets/post2.jpg" v-lazy1 alt=""><img src="@/assets/post3.jpg" v-lazy1 alt=""><img src="@/assets/post4.jpg" v-lazy1 alt=""><img src="@/assets/post5.jpg" v-lazy1 alt=""><img src="@/assets/post6.jpg" v-lazy1 alt=""></div></template><script>export default {name: 'lazyImg',components: {}}</script>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。