-
-
Notifications
You must be signed in to change notification settings - Fork 9.5k
Expand file tree
/
Copy pathlazy-image.js
More file actions
125 lines (116 loc) · 3.05 KB
/
lazy-image.js
File metadata and controls
125 lines (116 loc) · 3.05 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
* This is a fork of [vue-lazyload](https://github.com/hilongjw/vue-lazyload) with Vue 3 support.
* license at https://github.com/hilongjw/vue-lazyload/blob/master/LICENSE
*/
import { useRect } from '@vant/use';
import { loadImageAsync } from './util';
import { noop } from '../../utils';
import {
h,
ref,
reactive,
defineComponent,
getCurrentInstance,
onMounted,
onBeforeUnmount,
watch,
} from 'vue';
export default (lazyManager) =>
defineComponent({
props: {
src: [String, Object],
tag: {
type: String,
default: 'img',
},
},
setup(props, { slots }) {
const instance = getCurrentInstance();
const renderSrc = ref('');
const options = {
src: '',
error: '',
loading: '',
attempt: lazyManager.options.attempt,
};
const state = reactive({
loaded: false,
error: false,
attempt: 0,
});
const init = () => {
const { src, loading, error } = lazyManager.valueFormatter(props.src);
state.loaded = false;
options.src = src;
options.error = error;
options.loading = loading;
renderSrc.value = options.loading;
};
const lazyBox = {
get el() {
return instance.proxy.$el;
},
get $el() {
return instance.proxy.$el;
},
get $parent() {
return instance.proxy.$parent;
},
state,
options,
checkInView() {
const rect = useRect(instance.proxy.$el);
return (
rect.top < window.innerHeight * lazyManager.options.preLoad &&
rect.bottom > 0 &&
rect.left < window.innerWidth * lazyManager.options.preLoad &&
rect.right > 0
);
},
load(onFinish = noop) {
if (state.attempt > options.attempt - 1 && state.error) {
if (
process.env.NODE_ENV !== 'production' &&
!lazyManager.options.silent
) {
console.log(
`[@vant/lazyload] ${options.src} tried too more than ${options.attempt} times`,
);
}
onFinish();
return;
}
const { src } = options;
loadImageAsync(
{ src },
({ src }) => {
renderSrc.value = src;
state.loaded = true;
},
() => {
state.attempt++;
renderSrc.value = options.error;
state.error = true;
},
);
},
};
init();
watch(
() => props.src,
() => {
init();
lazyManager.addLazyBox(lazyBox);
lazyManager.lazyLoadHandler();
},
);
onMounted(() => {
lazyManager.addLazyBox(lazyBox);
lazyManager.lazyLoadHandler();
});
onBeforeUnmount(() => {
lazyManager.removeComponent(lazyBox);
});
return () => h(props.tag, { src: renderSrc.value }, slots.default?.());
},
});