Browser
useImage
https://www.vueusejs.com/core/useImage/
在浏览器中响应式加载图像,你可以等待结果显示或显示一个回退方案
基本使用
vue
<template>
<span v-if="isLoading">Loading ...</span>
<img
v-else
:src="avatarUrl"
alt="图片" />
</template>
<script setup>
import { useImage } from '@vueuse/core'
</script>
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
ts
import { watch } from 'vue-demi'
import type { MaybeRefOrGetter } from '@vueuse/shared'
import { toValue } from '@vueuse/shared'
import type { UseAsyncStateOptions } from '../useAsyncState'
import { useAsyncState } from '../useAsyncState'
export interface UseImageOptions {
/** Address of the resource */
src: string
/** Images to use in different situations, e.g., high-resolution displays, small monitors, etc. */
srcset?: string
/** Image sizes for different page layouts */
sizes?: string
/** Image alternative information */
alt?: string
/** Image classes */
class?: string
/** Image loading */
loading?: HTMLImageElement['loading']
/** Image CORS settings */
crossorigin?: string
/** Referrer policy for fetch https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy */
referrerPolicy?: HTMLImageElement['referrerPolicy']
}
async function loadImage(options: UseImageOptions): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image()
const { src, srcset, sizes, class: clazz, loading, crossorigin, referrerPolicy } = options
img.src = src
if (srcset) img.srcset = srcset
if (sizes) img.sizes = sizes
if (clazz) img.className = clazz
if (loading) img.loading = loading
if (crossorigin) img.crossOrigin = crossorigin
if (referrerPolicy) img.referrerPolicy = referrerPolicy
img.onload = () => resolve(img)
img.onerror = reject
})
}
/**
* 在浏览器中响应式加载图像,您可以等待结果显示它.
*
* @see https://vueuse.org/useImage
* @param options Image attributes, as used in the <img> tag
* @param asyncStateOptions
*/
export function useImage<Shallow extends true>(
options: MaybeRefOrGetter<UseImageOptions>,
asyncStateOptions: UseAsyncStateOptions<Shallow> = {}
) {
const state = useAsyncState<HTMLImageElement | undefined>(
() => loadImage(toValue(options)),
undefined,
{
resetOnExecute: true,
...asyncStateOptions,
}
)
watch(
() => toValue(options),
() => state.execute(asyncStateOptions.delay),
{ deep: true }
)
return state
}
export type UseImageReturn = ReturnType<typeof useImage>
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
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
作为组件
vue
<template>
<UseImage src="https://place.dog/300/200">
<template #loading> Loading.. </template>
<template #error> Failed </template>
</UseImage>
</template>
<script setup>
import UseImage from '@vueuse/components'
</script>
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
ts
import { defineComponent, h, reactive } from 'vue-demi'
import { useImage } from '../useImage'
import type { UseImageOptions } from '../useImage'
import type { RenderableComponent } from '../types'
export const UseImage = /* #__PURE__ */ defineComponent<UseImageOptions & RenderableComponent>({
name: 'UseImage',
props: [
'src',
'srcset',
'sizes',
'as',
'alt',
'class',
'loading',
'crossorigin',
'referrerPolicy',
] as unknown as undefined,
setup(props, { slots }) {
const data = reactive(useImage(props))
return () => {
if (data.isLoading && slots.loading) return slots.loading(data)
else if (data.error && slots.error) return slots.error(data.error)
if (slots.default) return slots.default(data)
return h(props.as || 'img', props)
}
},
})
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
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