最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue使用<Suspense/>實(shí)現(xiàn)圖片加載組件

 更新時(shí)間:2026年01月25日 10:44:37   作者:咸魚(yú)翻身更入味  
Suspense是Vue的內(nèi)置組件,用于管理異步組件的加載狀態(tài),包括等待、出錯(cuò)和最終渲染,它通過(guò)兩個(gè)插槽(default和fallback)來(lái)實(shí)現(xiàn)這一功能,感興趣的可以了解一下

什么是Suspense?

SuspenseVue的內(nèi)置組件,能讓你管理組件加載時(shí)的等待、出錯(cuò)和最終渲染邏輯。

主要配合異步組件、async/await 版的 setup() 使用。

它提供兩個(gè)插槽:

  • default(默認(rèn)插槽):要渲染的異步內(nèi)容
  • fallback:等待異步內(nèi)容加載時(shí)顯示的兜底內(nèi)容

話不多說(shuō),上代碼:

第一步,實(shí)現(xiàn)圖片異步組件

<template>
    <img 
    :src="props.src" 
    :alt="props.alt" 
    :style="{ 
      width: setWidth, 
      height: setHeight, 
      borderRadius: rounded, 
      objectFit: 'cover'
    }"
    />
</template>
// =================================== 此處為計(jì)算屬性邏輯 ================================
<script setup lang="ts">
import { computed, ref } from "vue";

// 圖片形狀可選項(xiàng)
type ShapeOption = "circle" | "square" | "roundRect";

interface ILazyImage {
  src: string;
  width:string|number;
  height:string|number;
  delay?:number;//延遲執(zhí)行?
  timeout?:number;//超時(shí)時(shí)間?
  shape?:ShapeOption;//圖片形狀
  alt?:string;
}

const props = defineProps<ILazyImage>();

//計(jì)算超時(shí)
const timeoutSet = computed(() => {
    let time = Number(props.timeout) || 5;
    return time * 1000;
});

//計(jì)算延遲
const delayTime = computed(() => {
    let time = Number(props.delay) || 0.1;
    return time * 1000;
});


//計(jì)算寬度
const setWidth = computed(() => {
    const val = parseFloat(props.width)
    if(!val) return '100px'
    return val  + "px";
});

//計(jì)算高度
const setHeight = computed(() => {
    const val = parseFloat(props.Height)
    if(!val) return '100px'
    return val  + "px";
});

// 計(jì)算圓角
const rounded = computed(() => {
    switch (props.shape) {
        case "circle":
            return "50%";
        case "square":
            return "0";
        case "roundRect":
            return "10px";
        default:
            return "10px";
    }
});

//========================實(shí)現(xiàn)異步加載圖片==================================

const loadImage = (src: string) => {
    return new Promise((resolve, reject) => {
    // 創(chuàng)建一個(gè)AbortController,用于取消請(qǐng)求
        const controller = new AbortController();
        const signal = controller.signal;

        const timeoutId = setTimeout(() => {
        // 超時(shí)時(shí)取消請(qǐng)求
            controller.abort();
            reject(new Error("圖片加載超時(shí)"));
        }, timeoutSet.value);

        setTimeout(() => {
            const image = new Image();
            image.src = src;
            image.onload = () => {
                clearTimeout(timeoutId);
                resolve(src);
            };
            image.onerror = () => {
                clearTimeout(timeoutId);
                reject(new Error("圖片加載失敗"));
            };
        }, delayTime.value);
    });
};

// 執(zhí)行圖片加載(async/await 觸發(fā) Suspense 等待)
await loadImage(props.src);

</script>

第二步:實(shí)現(xiàn)懶加載組件

  • default(默認(rèn)插槽):要渲染的異步內(nèi)容
  • fallback:等待異步內(nèi)容加載時(shí)顯示的兜底內(nèi)容
  • 使用v-bind()綁定屬性

<Suspense></Suspense>中直接使用異步組件即可,<template #fallback></template>則是加載時(shí)顯示

<template>
    <div>
        <Suspense>
            <template #default>
                <div class="image">
                    <Image v-bind="{ ...props }"></Image>
                </div>
            </template>
            <template #fallback>
                <div class="skeleton"></div>
            </template>
        </Suspense>
    </div>
</template>

<script setup lang="ts">
import { computed } from "vue";
import Image from "./Image.vue";
// 圖片形狀可選項(xiàng)
type ShapeOption = "circle" | "square" | "roundRect";

interface ILazyImage {
  src: string;
  width:string|number;
  height:string|number;
  delay?:number;//延遲執(zhí)行?
  timeout?:number;//超時(shí)時(shí)間?
  shape?:ShapeOption;//圖片形狀
  alt?:string;
}

const props = defineProps<ILazyImage>();

//計(jì)算超時(shí)
const timeoutSet = computed(() => {
    let time = Number(props.timeout) || 5;
    return time * 1000;
});

//計(jì)算延遲
const delayTime = computed(() => {
    let time = Number(props.delay) || 0.1;
    return time * 1000;
});


//計(jì)算寬度
const setWidth = computed(() => {
    const val = parseFloat(props.width)
    if(!val) return '100px'
    return val  + "px";
});

//計(jì)算高度
const setHeight = computed(() => {
    const val = parseFloat(props.Height)
    if(!val) return '100px'
    return val  + "px";
});

// 計(jì)算骨架屏動(dòng)畫(huà):遮罩寬度(取容器寬度的 40%) 
const setSeletonWidth = computed(() => { 
    // 提取寬度數(shù)值(兼容 px 單位) 
    const widthNum = parseFloat(setWidth.value) || 100; 
    return `${widthNum * 0.4}px`;
}); 


// 骨架屏動(dòng)畫(huà)起始位置(從容器左側(cè)外 30% 開(kāi)始)
const setSeletonStartRight = computed(() => { 
    const widthNum = parseFloat(setWidth.value) || 100; 
    return `-${widthNum * 1.3}px`;  // 起始在容器左側(cè)外
});

// 骨架屏動(dòng)畫(huà)結(jié)束位置(到容器右側(cè)外 30%) 
const setSeletonEndRight = computed(() => { 
    const widthNum = parseFloat(setWidth.value) || 100; return `${widthNum * 1.3}px`;
    // 結(jié)束在容器右側(cè)外
});

// 計(jì)算圓角
const rounded = computed(() => {
    switch (props.shape) {
        case "circle":
            return "50%";
        case "square":
            return "0";
        case "roundRect":
            return "10px";
        default:
            return "10px";
    }
});
</script>

<style scoped>
.image {
    overflow: hidden;
}

.skeleton {
    width: v-bind(setWidth);
    height: v-bind(setHeight);
    background-color: #dfe4ea;
    overflow: hidden;
    position: relative;

    border-radius: v-bind(rounded);
}

.skeleton::before {
    content: "";
    display: block;
    background-color: #ced6e0;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
    position: absolute;
    top: 0;
    right: v-bind(setSeletonStartRight);
    width: v-bind(setSeletonWidth);
    height: v-bind(setHeight);
    transform: skewX(-30deg);
    animation: ping 1s infinite ease-out;
    filter: blur(10px);
}

@keyframes ping {
    from {
        right: v-bind(setSeletonStartRight);
    }

    to {
        right: v-bind(setSeletonEndRight);
    }
}
</style>

補(bǔ)充

  • 代碼內(nèi)有些重復(fù)的內(nèi)容,可使用另外的ts來(lái)聲明或?qū)崿F(xiàn)。
  • 其中可能有些變量或?qū)崿F(xiàn)過(guò)程有誤,此文章僅供參考。

到此這篇關(guān)于Vue使用&lt;Suspense/&gt;實(shí)現(xiàn)圖片加載組件的文章就介紹到這了,更多相關(guān)Vue &lt;Suspense/&gt;圖片加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue之字符串、數(shù)組之間的相互轉(zhuǎn)換方式

    vue之字符串、數(shù)組之間的相互轉(zhuǎn)換方式

    這篇文章主要介紹了vue之字符串、數(shù)組之間的相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • VUE?mixin?使用示例詳解

    VUE?mixin?使用示例詳解

    混入mixin提供了一種非常靈活的方式,來(lái)分發(fā)Vue組件中的可復(fù)用功能,一個(gè)混入對(duì)象可以包含任意組件選項(xiàng),接下來(lái)通過(guò)本文給大家介紹VUE?mixin?使用,需要的朋友可以參考下
    2022-08-08
  • vue實(shí)現(xiàn)動(dòng)態(tài)表格提交參數(shù)動(dòng)態(tài)生成控件的操作

    vue實(shí)現(xiàn)動(dòng)態(tài)表格提交參數(shù)動(dòng)態(tài)生成控件的操作

    這篇文章主要介紹了vue實(shí)現(xiàn)動(dòng)態(tài)表格提交參數(shù)動(dòng)態(tài)生成控件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • vue圓形進(jìn)度條環(huán)形進(jìn)度條組件內(nèi)部顯示圖片示例

    vue圓形進(jìn)度條環(huán)形進(jìn)度條組件內(nèi)部顯示圖片示例

    這篇文章主要為大家介紹了vue圓形進(jìn)度條環(huán)形進(jìn)度條組件內(nèi)部顯示圖片示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 基于vue-cli創(chuàng)建的項(xiàng)目的目錄結(jié)構(gòu)及說(shuō)明介紹

    基于vue-cli創(chuàng)建的項(xiàng)目的目錄結(jié)構(gòu)及說(shuō)明介紹

    下面小編就為大家分享一篇基于vue-cli創(chuàng)建的項(xiàng)目的目錄結(jié)構(gòu)及說(shuō)明介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助
    2017-11-11
  • 深入淺出分析vue2和vue3的區(qū)別

    深入淺出分析vue2和vue3的區(qū)別

    這篇文章主要介紹了vue2和vue3的區(qū)別,較為詳細(xì)的分析了vue2與vue3的常見(jiàn)區(qū)別與使用方法,需要的朋友可以參考下
    2023-06-06
  • 解決Vue+SpringBoot+Shiro跨域問(wèn)題

    解決Vue+SpringBoot+Shiro跨域問(wèn)題

    本文將結(jié)合實(shí)例代碼,解決Vue+SpringBoot+Shiro跨域問(wèn)題,相信大家剛開(kāi)始做都會(huì)遇到這個(gè)問(wèn)題,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • VUE3中watch和watchEffect的用法詳解

    VUE3中watch和watchEffect的用法詳解

    本文主要介紹了VUE3中watch和watchEffect的用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解vue之mixin的使用

    詳解vue之mixin的使用

    這篇文章主要為大家介紹了vue之mixin的使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-11-11
  • vue中的proxyTable反向代理(親測(cè)有用)

    vue中的proxyTable反向代理(親測(cè)有用)

    這篇文章主要介紹了vue中的proxyTable反向代理(親測(cè)有用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04

最新評(píng)論

河津市| 喀喇沁旗| 兴海县| 龙里县| 忻州市| 双柏县| 泾阳县| 富顺县| 葫芦岛市| 昆明市| 洪洞县| 阳江市| 临清市| 滨海县| 莲花县| 襄垣县| 金山区| 和硕县| 明星| 云霄县| 凤阳县| 深水埗区| 中江县| 集贤县| 黑山县| 霞浦县| 大埔县| 射洪县| 嘉祥县| 阿克| 临沂市| 眉山市| 黄梅县| 南宁市| 阿尔山市| 芜湖市| 杭锦旗| 锡林郭勒盟| 教育| 景德镇市| 鄂伦春自治旗|