진행하고 있는 프로젝트에 ImagelazyLoading을 적용시키면서
해당 기능을 directive로 만들어 봤다.
v-if, v-for와 같은 나만의 디렉티브를 만들 수 있는 기능이다.
참고: https://vuejs.org/guide/reusability/custom-directives.html
나는 커스텀 디렉티브를 전역적으로 사용하기 위해
전역적으로 등록했다.
src > directives > lazyLoad.js

lazyLoad.js 파일
// lazyLoad.js
export default {
mounted(el) {
// Intersection Observer를 지원하지 않는 브라우저의 경우
// backgroundImage에 바로 이미지 로딩시켜줌
const loadBackgroundImage = () => {
if (el.className.includes('lazy')) {
const imageUrl = el.dataset.imageurl;
el.style.backgroundImage = `url(${imageUrl})`;
}
};
// Intersection Observer를 지원하는 브라우저의 경우
// Observer 관찰자 만들어
// 스크롤에 따라 이미지 로딩할 수 있도록 만들어줌
const createObserver = () => {
const observerOption = {
root: null, // 뷰포트를 기준으로 관찰
rootMargin: '0px 0px 100px 0px', // 아래로 100px까지는 관찰 대상으로 간주
threshold: 0.5, // 관찰 대상의 50% 이상이 보일 때 콜백 호출
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
loadBackgroundImage();
observer.unobserve(el);
}
});
}, observerOption);
observer.observe(el)
};
window['IntersectionObserver']
? createObserver()
: loadBackgroundImage();
},
};
✔️참고하면 좋을 팁! Directive Hooks
디렉티브 정의 객체는 다음과 같은 여러 훅을 사용할 수 있다.
모든 훅은 필수 아닌 선택!( 나의 경우 mounted()훅을 사용함 )
const myDirective = {
// 바인딩된 요소의 속성 전에 호출됨
// 또는 이벤트 리스너가 적용됨
created(el, binding, vnode, prevVnode) {
// 인수에 대한 자세한 내용은 아래를 참조하십시오.
},
// 요소가 DOM에 삽입되기 직전에 호출됩니다.
beforeMount() {},
// 바인딩된 요소의 부모 구성 요소가 있을 때 호출됩니다.
// 모든 자식이 마운트됩니다.
mounted() {},
// 상위 컴포넌트가 업데이트되기 전에 호출됨
beforeUpdate() {},
// 상위 컴포넌트 다음에 호출되고
// 모든 자식이 업데이트되었습니다.
updated() {},
// 상위 컴포넌트가 마운트 해제되기 전에 호출됨
beforeUnmount() {},
// 상위 컴포넌트가 마운트 해제될 때 호출됩니다.
unmounted() {}
}
}
src > main.js
import lazyLoad from './directives/lazyLoad.js'
app.directive('lazyLoad', lazyLoad)
위처럼 작성하면 directive가 등록된다.
등록한 directive를 사용하고 싶으면 v-if, v-for처럼 'v'접두사를 붙여 사용하면 된다.
<div v-lazy-load>
필요한 코드 작성
</div>
수많은 구글링의 합작이지만
lazyLoading과 customDirective를 합쳐서 하나 만들어내니
괜시리 으쓱해졌다 으쓱으쓱..헿 😁