Vue是可以自定義指令的,最近學習過程中遇見了一個需要圖片懶加載的功能,最后參考了別人的代碼和思路自己重新寫了一遍。以下將詳細介紹如何實現自定義指令v-lazyload。
先看如何使用這個指令:
1
|
<img v-lazyload=
"imageSrc"
>
|
imageSrc是要加載的圖片的實際路徑。
為了實現這個指令,我們首先單獨建立一個文件,名字為lazyload.js.並填寫基本的代碼,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//Vue 圖片懶加載,導出模塊
export
default
(Vue , options = {})=>{
//初始化的選項,default是未加載圖片時顯示的默認圖片
var
init = {
}
//addListener為Vue指令的具體實現功能函數,我們這里為所有使用v-lazyload的指令的元素添加監聽
//ele 是dom元素,binding是綁定的具體值,
//例如:<img v-lazyload="imageSrc" > ele是img binding是imageSrc
const addListenner = (ele,binding) =>{
}
//Vue自定義指令,lazyload為指令的名稱
Vue.directive(
'lazyload'
,{
inserted:addListener,
updated:addListener
})
}
|
inserted 和 updated為Vue指令的執行不同階段提供的鈎子函數,查看Vue的官網可以看到一共有5個階段,
指令定義函數提供了幾個鈎子函數(可選):
bind: 只調用一次,指令第一次綁定到元素時調用,用這個鈎子函數可以定義一個在綁定時執行一次的初始化動作。
inserted: 被綁定元素插入父節點時調用(父節點存在即可調用,不必存在於 document 中)。
update: 被綁定元素所在的模板更新時調用,而不論綁定值是否變化。通過比較更新前后的綁定值,可以忽略不必要的模板更新(詳細的鈎子函數參數見下)。
componentUpdated: 被綁定元素所在模板完成一次更新周期時調用。
unbind: 只調用一次, 指令與元素解綁時調用。
這里我們只用inserted和updated就夠了。
接下來我們具體實現addListener的實現。我們的具體思路如下:
1、先看看這個圖片是否需要懶加載。有兩種情況,一是圖片還沒到達可視區域,二是圖片已經加載過了。
2、然后監聽窗口的scroll事件,判斷哪些圖片可以進行懶加載了。
這里我們需要一個需要進行監聽需要懶加載的圖片列表和一個需要記錄已經加載過得圖片列表。另外為了方便數組的操作,我們加一個數組的remove方法。
繼續我們的代碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
//Vue 圖片懶加載
export
default
(Vue , options = {})=>{
//數組item remove方法
if
(!Array.prototype.remove){
Array.prototype.remove =
function
(item){
if
(!
this
.length)
return
var
index =
this
.indexOf(item);
if
( index > -1){
this
.splice(index,1);
return
this
}
}
}
var
init = {
}
//需要進行監聽的圖片列表,還沒有加載過得
var
listenList = [];
//已經加載過得圖片緩存列表
var
imageCatcheList = [];
//是否已經加載過了
const isAlredyLoad = (imageSrc) => {
}
//檢測圖片是否可以加載,如果可以則進行加載
const isCanShow = (item) =>{
};
//添加監聽事件scroll
const onListenScroll = () =>{
}
//Vue 指令最終的方法
const addListener = (ele,binding) =>{
//綁定的圖片地址
var
imageSrc = binding.value;
//如果已經加載過,則無需重新加載,直接將src賦值
if
(isAlredyLoad(imageSrc)){
ele.src = imageSrc;
return
false
;
}
var
item = {
ele:ele,
src:imageSrc
}
//圖片顯示默認的圖片
ele.src = init.
default
;
//再看看是否可以顯示此圖片
if
(isCanShow(item)){
return
}
//否則將圖片地址和元素均放入監聽的lisenList里
listenList.push(item);
//然后開始監聽頁面scroll事件
onListenScroll();
}
Vue.directive(
'lazyload'
,{
inserted:addListener,
updated:addListener
})
}
|
接下來就幾個空方法的實現了。
isAlredyLoad ,判斷是否已經加載過了這個圖片
1
2
3
4
5
6
7
|
const isAlredyLoad = (imageSrc) => {
if
(imageCatcheList.indexOf(imageSrc) > -1){
return
true
;
}
else
{
return
false
;
}
}
|
isCanShow 圖片是否進入可視區域,如果已經進入則進行加載
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//檢測圖片是否可以加載,如果可以則進行加載
const isCanShow = (item) =>{
var
ele = item.ele;
var
src = item.src;
//圖片距離頁面頂部的距離
var
top = ele.getBoundingClientRect().top;
//頁面可視區域的高度
var
windowHeight = window.innerHight;
//top + 10 已經進入了可視區域10像素
if
(top + 10 < window.innerHeight){
var
image =
new
Image();
image.src = src;
image.onload =
function
(){
ele.src = src;
imageCatcheList.push(src);
listenList.remove(item);
}
return
true
;
}
else
{
return
false
;
}
};
|
onListenScroll監聽滾動事件,並且檢測是否進入可視區域。
1
2
3
4
5
6
7
8
|
const onListenScroll = () =>{
window.addEventListener(
'scroll'
,
function
(){
var
length = listenList.length;
for
(let i = 0;i<length;i++ ){
isCanShow(listenList[i]);
}
})
}
|
最終我們的代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
//Vue 圖片懶加載
export
default
(Vue , options = {})=>{
if
(!Array.prototype.remove){
Array.prototype.remove =
function
(item){
if
(!
this
.length)
return
var
index =
this
.indexOf(item);
if
( index > -1){
this
.splice(index,1);
return
this
}
}
}
var
init = {
lazyLoad:
false
,
}
var
listenList = [];
var
imageCatcheList = [];
const isAlredyLoad = (imageSrc) => {
if
(imageCatcheList.indexOf(imageSrc) > -1){
return
true
;
}
else
{
return
false
;
}
}
//檢測圖片是否可以加載,如果可以則進行加載
const isCanShow = (item) =>{
var
ele = item.ele;
var
src = item.src;
//圖片距離頁面頂部的距離
var
top = ele.getBoundingClientRect().top;
//頁面可視區域的高度
var
windowHeight = window.innerHight;
//top + 10 已經進入了可視區域10像素
if
(top + 10 < window.innerHeight){
var
image =
new
Image();
image.src = src;
image.onload =
function
(){
ele.src = src;
imageCatcheList.push(src);
listenList.remove(item);
}
return
true
;
}
else
{
return
false
;
}
};
const onListenScroll = () =>{
window.addEventListener(
'scroll'
,
function
(){
var
length = listenList.length;
for
(let i = 0;i<length;i++ ){
isCanShow(listenList[i]);
}
})
}
//Vue 指令最終的方法
const addListener = (ele,binding) =>{
//綁定的圖片地址
var
imageSrc = binding.value;
//如果已經加載過,則無需重新加載,直接將src賦值
if
(isAlredyLoad(imageSrc)){
ele.src = imageSrc;
return
false
;
}
var
item = {
ele:ele,
src:imageSrc
}
//圖片顯示默認的圖片
ele.src = init.
default
;
//再看看是否可以顯示此圖片
if
(isCanShow(item)){
return
}
//否則將圖片地址和元素均放入監聽的lisenList里
listenList.push(item);
//然后開始監聽頁面scroll事件
onListenScroll();
}
Vue.directive(
'lazyload'
,{
inserted:addListener,
updated:addListener
})
}
|
使用時需要在主文件中引入這個文件,並且vue.use();
1
2
|
import LazyLoad from
'lazyLoad.js'
Vue.use(LazyLoad);
|
並且在需要懶加載的圖片上均按照如下使用v-lazyload指令即可
<img v-lazyload="imageSrc" >
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。