1. Introduction to project implementation
Vue Project Construction Refer to Webpack4 VUE Project Construction
Vuepress is the official document of vuepress.vuejs.org
Github Pages + gh-page
The project addressGithub.com/zxpsuper/vu…
File address zxpsuper.github. IO /vui-vue
In the stage of self exploration, looking forward to leaving your valuable advice!
2. Basic implementation of V-lazy
The basic principle of lazy image loading:
- Replace the target image with a placeholder first
src
Attribute values - As the picture of the
offsetTop < innerHeight + scrollTop
, that is, the picture appears inside the window, then modifysrc
A value ofdata-src
The value of the - Of course, all this requires constant listening for rolling events
Start by implementing a lazy loading function
var img = document.getElementsByTagName('img');
function lazyload() {
// Listen for page scroll events
var seeHeight = window.innerHeight; // Height of visible area
var scrollTop =
document.documentElement.scrollTop || document.body.scrollTop; // Height of scroll bar from top
for (var i = 0; i < img.length; i++) {
if (img[i].getAttribute('data-image-show')) continue; // If the load is complete, there is no need to go through the following process
if (img[i].offsetTop < seeHeight + scrollTop) {
console.log(img[i].offsetTop, seeHeight, scrollTop);
if (img[i].getAttribute('src') == Vue.$vuiLazyLoad.img) {
img[i].src = img[i].getAttribute('data-src');
img[i].setAttribute('data-image-show'.'true'); // Indicate that the load is complete}}}}Copy the code
Scroll to monitor
Scroll monitoring, continuous scrolling will continue to trigger the function of scroll monitoring, affecting performance, so it is necessary to add an anti-shake function
// The buffeting function
function debounce(event, time) {
let timer = null;
return function(. args) {
if (timer) clearTimeout(timer)
timer = setTimeout((a)= > {
timer = null;
event.apply(this, args);
}, time);
};
}
Copy the code
Add and remove listeners
window.removeEventListener('scroll', debounce(lazyload, 800));
window.addEventListener('scroll', debounce(lazyload, 800));
Copy the code
Add the instruction
We use the three hook functions in the custom directive bind, INSERTED, and unbind, and we want to make the placeholder in the directive modifiable, so we write it as a function
const lazyload = function(Vue) {
var img = document.getElementsByTagName('img'), evenFunction;
function lazyload() {
// Listen for page scroll events
var seeHeight = window.innerHeight; // Height of visible area
var scrollTop =
document.documentElement.scrollTop || document.body.scrollTop; // Height of scroll bar from top
for (var i = 0; i < img.length; i++) {
if (img[i].getAttribute('data-image-show')) continue; // If the load is complete, there is no need to go through the following process
if (img[i].offsetTop < seeHeight + scrollTop) {
console.log(img[i].offsetTop, seeHeight, scrollTop);
if (img[i].getAttribute('src') == Vue.$vuiLazyLoad.img) {
img[i].src = img[i].getAttribute('data-src');
img[i].setAttribute('data-image-show'.'true'); // Indicate that the load is complete}}}}// The default configuration in vUI. You can modify the placeholder map by modifying Vue.$vuiLazyLoad
Vue.$vuiLazyLoad = {
img:
'https://github.com/zxpsuper/Demo/blob/master/images/avatar.jpg?raw=true'.imgLength: 0.// The number of lazy images to load, when the number is 0 remove the scroll listener
};
lazyload(); // when the page is loaded, the image in the area is loaded
evenFunction = debounce(lazyload, 800);
window.removeEventListener('scroll', evenFunction);
window.addEventListener('scroll', evenFunction);
return {
name: 'lazy'./ / binding
bind(el, binding) {
el.setAttribute('src', Vue.$vuiLazyLoad.img);
el.setAttribute('data-src', binding.value);
Vue.$vuiLazyLoad.imgLength++;
},
/ / insert
inserted(el) {
/ / empty for the time being
},
/ / unbundling
unbind() {
Vue.$vuiLazyLoad.imgLength--; // Each time you unbind, subtract
if(! Vue.$vuiLazyLoad.imgLength && evenFunction)window.removeEventListener('scroll', evenFunction); }}; }Copy the code
Using new featuresIntersectionObserver
The IntersectionObserver interface (which is part of the IntersectionObserver API) provides developers with a way to asynchronously monitor the intersectionstate of a target element with its ancestors or viewports.
Check to see if the element crosses the window, if so, change the SCR to data-src, and remove the observation state. Of course, all this is provided that you observe the image itself at the time of image creation, and therefore in the hook function at image insertion
inserted(el) {
if (IntersectionObserver) lazyImageObserver.observe(el);
},
Copy the code
Specific use method:
let lazyImageObserver
if (IntersectionObserver) {
lazyImageObserver = new IntersectionObserver((entries, observer) = > {
entries.forEach((entry, index) = > {
let lazyImage = entry.target;
// If the element is visible
if (entry.intersectionRatio > 0) {
if (lazyImage.getAttribute('src') == Vue.$vuiLazyLoad.img) {
lazyImage.src = lazyImage.getAtstribute('data-src');
}
lazyImageObserver.unobserve(lazyImage); // Remove the observation}}); }); }Copy the code
Of course, IntersectionObserver is preferred. Otherwise, traditional methods will be used
Registration instructions
import Vue from 'vue'
Vue.directive('lazy', lazyLoad(Vue));
Copy the code
3. Complete code
const lazyLoad = function(Vue) {
var img = document.getElementsByTagName('img');
function lazyload() {
console.log('rolling lazy');
// Listen for page scroll events
var seeHeight = window.innerHeight; // Height of visible area
var scrollTop =
document.documentElement.scrollTop || document.body.scrollTop; // Height of scroll bar from top
for (var i = 0; i < img.length; i++) {
if (img[i].getAttribute('data-image-show')) continue;
if (img[i].offsetTop < seeHeight + scrollTop) {
console.log(img[i].offsetTop, seeHeight, scrollTop);
if (img[i].getAttribute('src') == Vue.$vuiLazyLoad.img) {
img[i].src = img[i].getAttribute('data-src');
img[i].setAttribute('data-image-show'.'true');
}
}
}
}
Vue.$vuiLazyLoad = {
img:
'https://github.com/zxpsuper/Demo/blob/master/images/avatar.jpg?raw=true'.imgLength: 0};var lazyImageObserver, evenFunction;
if (IntersectionObserver) {
lazyImageObserver = new IntersectionObserver((entries, observer) = > {
entries.forEach((entry, index) = > {
let lazyImage = entry.target;
// If the element is visible
if (entry.intersectionRatio > 0) {
if (lazyImage.getAttribute('src') == Vue.$vuiLazyLoad.img) {
lazyImage.src = lazyImage.getAttribute('data-src'); } lazyImageObserver.unobserve(lazyImage); }}); }); }else {
lazyload(); // when the page is loaded, the image in the area is loaded
evenFunction = debounce(lazyload, 800);
window.removeEventListener('scroll', evenFunction);
window.addEventListener('scroll', evenFunction);
}
return {
name: 'lazy',
bind(el, binding) {
el.setAttribute('src', Vue.$vuiLazyLoad.img);
el.setAttribute('data-src', binding.value);
Vue.$vuiLazyLoad.imgLength++;
},
inserted(el) {
if (IntersectionObserver) lazyImageObserver.observe(el);
},
unbind() {
Vue.$vuiLazyLoad.imgLength--;
if(! Vue.$vuiLazyLoad.imgLength && evenFunction)window.removeEventListener('scroll', evenFunction); }}; };export default lazyLoad;
function debounce(event, time) {
let timer = null;
return function(. args) {
if (timer) clearTimeout(timer);
timer = setTimeout((a)= > {
timer = null;
event.apply(this, args);
}, time);
};
}
Copy the code
conclusion
This article is the comprehensive realization of vUE custom instruction and lazy loading principle, if there are mistakes, hope to point out common progress.
More recommended
Advanced_front_end
Daily question
Webpack4 Build Vue application (createVue)
Canvas Advanced (1) Generation of two-dimensional code and scan code recognition
Canvas advanced (2) Write a NPM plug-in to generate a TWO-DIMENSIONAL code with logo
Canvas advanced (3) TS + Canvas rewrite “color discrimination” small game
Canvas advanced (four) to achieve a “scratch-off” game