VUE解決圖片視頻加載緩慢/首屏加載白屏的問題
1 問題描述
在 Vue3 項目中,有時候會出現(xiàn)圖片視頻加載緩慢、首屏加載白屏的問題
2 原因分析
通常是由以下原因?qū)е碌模?/p>
圖片或視頻格式不當:如果圖片或視頻格式選擇不當,比如選擇了無損壓縮格式,可能會導致文件大小過大,從而影響加載速度。
頁面中同時加載了大量的圖片和視頻,導致請求次數(shù)過多,網(wǎng)絡(luò)傳輸速度受限,從而影響頁面加載速度。
頁面中的圖片和視頻沒有進行優(yōu)化處理,比如沒有進行壓縮、沒有使用 CDN 加速等。
頁面的 HTML、CSS、JavaScript 代碼沒有進行優(yōu)化,比如沒有使用 webpack 進行打包、沒有使用代碼分割技術(shù)等,導致頁面加載時間過長。
頁面中的圖片和視頻沒有使用懶加載技術(shù),導致頁面一次性加載過多的資源,從而導致頁面加載速度變慢。
網(wǎng)絡(luò)狀況不佳,比如網(wǎng)絡(luò)延遲、帶寬受限等,都可能導致圖片和視頻加載緩慢。
服務器響應時間過長:如果服務器響應時間過長,會導致頁面請求資源的時間變慢,從而影響頁面加載速度。
使用了不穩(wěn)定的第三方庫:如果使用了不穩(wěn)定的第三方庫或者組件,可能會導致頁面加載速度變慢。
瀏覽器緩存策略不當:如果瀏覽器緩存策略設(shè)置不當,可能會導致瀏覽器重復請求資源,從而影響頁面加載速度。
網(wǎng)絡(luò)安全策略較為嚴格:如果網(wǎng)絡(luò)安全策略較為嚴格,可能會導致瀏覽器請求資源時遇到一些限制,從而影響頁面加載速度。
因此,在開發(fā) Vue3 項目時,需要注意對圖片和視頻進行優(yōu)化處理,減少請求次數(shù),使用懶加載技術(shù),優(yōu)化代碼等,來提升頁面加載速度,避免出現(xiàn)加載緩慢、首屏加載白屏的問題。
3 解決方案
圖片和視頻加載緩慢、導致首屏加載白屏的問題,通常可以從以下幾個方面入手來解決:
- 圖片和視頻的優(yōu)化
- 懶加載
- 骨架屏
- 代碼優(yōu)化
3.1 圖片和視頻的優(yōu)化
可以通過圖片壓縮、視頻壓縮等技術(shù)來減小文件大小,從而提高加載速度。同時,還可以通過 CDN 加速來加快資源加載速度。
可以從以下幾個方法入手:
- 壓縮圖片或視頻
- 選擇合適的圖片或視頻格式
- 使用圖片或視頻 CDN 加速
- 使用懶加載技術(shù)
3.1.1 壓縮圖片或視頻
可以使用圖片或視頻壓縮工具,將文件大小壓縮至合適的大小。對于圖片,可以使用在線圖片壓縮工具或者 Photoshop 等圖片編輯軟件進行壓縮;對于視頻,可以使用視頻壓縮軟件,如 HandBrake 等進行壓縮。
壓縮工具推薦
以下是幾個常用的在線圖片壓縮工具:
- TinyPNG(tinypng.com)
TinyPNG 是一個免費的在線圖片壓縮工具,可以將 PNG 和 JPEG 格式的圖片壓縮至合適的大小,而且不會影響圖片質(zhì)量。
- Compressor.io(compressor.io)
Compressor.io 是一個免費的在線圖片壓縮工具,可以壓縮 JPEG、PNG、SVG 和 GIF 等格式的圖片。它可以將圖片壓縮至較小的大小,而且不會影響圖片質(zhì)量。
- Kraken(kraken.io)
Kraken 是一個在線圖片優(yōu)化和壓縮服務,可以將 JPEG、PNG 和 GIF 等格式的圖片壓縮至最小的文件大小。Kraken 還提供了 API 接口,可以方便地集成到項目中。
- ImageOptim(imageoptim.com)
ImageOptim 是一個免費的圖片優(yōu)化工具,它可以自動壓縮 JPEG、PNG 和 GIF 等格式的圖片,并且可以自動刪除圖片中的元數(shù)據(jù)和不必要的信息,從而減小文件大小。
3.1.2 選擇合適的圖片或視頻格式
選擇合適的圖片或視頻格式也可以減小文件大小。例如,對于圖片,可以選擇 JPEG 或者 WebP 格式,對于視頻,可以選擇 H.264 或者 H.265 格式。
3.1.3 使用圖片或視頻 CDN 加速
可以使用圖片或視頻 CDN 加速,將圖片或視頻資源分布在全球各地的 CDN 節(jié)點上,從而加快資源的傳輸速度,提高頁面加載速度。
3.1.4 使用懶加載技術(shù)
可以使用懶加載技術(shù),將圖片或視頻的加載延遲到用戶需要訪問它們時再加載,從而減少頁面一次性請求過多的資源,提高頁面加載速度。
3.2 懶加載
使用懶加載技術(shù),可以將圖片和視頻的加載延遲到用戶需要訪問它們時再加載,從而減少頁面一次性加載過多的資源,提高首屏加載速度。
以下是使用懶加載技術(shù)實現(xiàn)圖片和視頻懶加載的方法:
使用 Intersection Observer API
使用 Intersection Observer API
Intersection Observer API 是一種新的瀏覽器 API,可以監(jiān)聽指定元素是否進入了視口,從而觸發(fā)回調(diào)函數(shù)。
可以通過監(jiān)聽圖片或視頻元素是否進入了視口,從而觸發(fā)加載圖片或視頻的操作。
使用示例
當然可以,下面是一個使用 Intersection Observer API 實現(xiàn)圖片懶加載的 Vue 3 示例:
在組件中引入 Intersection Observer API
在 Vue 3 中,可以通過在組件中使用
onMounted
鉤子函數(shù)來引入 Intersection Observer API:
<template> <img v-for="image in images" :key="image.id" :src="image.placeholder" :data-src="image.src" alt=""> </template> <script> import { onMounted } from 'vue'; export default { name: 'LazyLoadImages', data() { return { images: [ { id: 1, src: 'path/to/image1.jpg', placeholder: 'path/to/placeholder1.jpg' }, { id: 2, src: 'path/to/image2.jpg', placeholder: 'path/to/placeholder2.jpg' }, // ... ] }; }, setup() { onMounted(() => { // 創(chuàng)建 IntersectionObserver 實例 const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { const lazyImage = entry.target; lazyImage.src = lazyImage.dataset.src; lazyImage.removeAttribute('data-src'); observer.unobserve(lazyImage); } }); }); // 監(jiān)聽圖片元素 const lazyImages = document.querySelectorAll('img[data-src]'); lazyImages.forEach(image => { observer.observe(image); }); }); } }; </script>
在上面的示例中,通過
onMounted
鉤子函數(shù)創(chuàng)建了 IntersectionObserver 實例,并在其中監(jiān)聽了所有帶有 "data-src" 屬性的圖片元素。當圖片元素進入視口時,我們通過
isIntersecting
屬性判斷圖片是否進入了視口,如果進入了視口就將 "data-src" 屬性的值賦給 "src" 屬性,從而加載圖片資源,同時移除 "data-src" 屬性,避免重復加載。最后,通過
unobserve
方法停止監(jiān)聽圖片元素。這樣,就成功地使用 Intersection Observer API 實現(xiàn)了圖片的懶加載。
使用第三方庫
除了使用 Intersection Observer API,還可以使用一些第三方庫來實現(xiàn)圖片和視頻的懶加載,
如 LazyLoad、Lozad.js、LazyLoad-xt 等。這些庫可以更快速地實現(xiàn)懶加載效果,并提供了更多的配置選項,例如觸發(fā)懶加載的條件、動畫效果等。具體使用方法可以參考它們的官方文檔。
使用示例
當然可以,以下是一個使用 LazyLoad 庫實現(xiàn)圖片懶加載的 Vue 3 示例:
安裝和引入 LazyLoad 庫
在終端中安裝 LazyLoad 庫:
npm install lazyload --save
然后,在 Vue 3 組件中引入 LazyLoad 庫:
<template> <img v-for="image in images" :key="image.id" :src="image.placeholder" data-src="image.src" alt=""> </template> <script> import LazyLoad from 'lazyload'; export default { name: 'LazyLoadImages', data() { return { images: [ { id: 1, src: 'path/to/image1.jpg', placeholder: 'path/to/placeholder1.jpg' }, { id: 2, src: 'path/to/image2.jpg', placeholder: 'path/to/placeholder2.jpg' }, // ... ] }; }, mounted() { // 初始化 LazyLoad const lazyLoadInstance = new LazyLoad({ elements_selector: 'img[data-src]', threshold: 0, // 配置選項 }); // 手動觸發(fā)加載 lazyLoadInstance.update(); } }; </script>
在上面的示例中,
先通過
npm install
命令安裝了 LazyLoad 庫,并在組件中引入了該庫。然后,在組件的
mounted
鉤子函數(shù)中初始化了 LazyLoad 并傳入了圖片元素的選擇器,以及其它一些配置選項。最后,通過
update
方法手動觸發(fā)圖片的加載。
這樣,就成功地使用 LazyLoad 庫實現(xiàn)了圖片的懶加載。
除了圖片懶加載,LazyLoad 庫還可以用于懶加載視頻、背景圖等資源。具體使用方法可以參考 LazyLoad 的官方文檔。
3.3 骨架屏
骨架屏(Skeleton Screen)是一種頁面加載優(yōu)化的技術(shù),可以在頁面加載過程中顯示一個簡單的灰色框架,代替還未加載的內(nèi)容。骨架屏可以提高用戶體驗,讓用戶感覺頁面加載速度更快,同時也可以減少用戶的焦慮感。
在 Vue 3 中,可以使用一些第三方庫來實現(xiàn)骨架屏效果,例如 vue-skeleton-webpack-plugin、vue-content-loader、vue-loading-skeleton 等。
3.3.1 如何在Vue 3中使用vue-content-loader實現(xiàn)骨架屏效果?
vue-content-loader
是一個 Vue.js 組件庫,可以幫助我們實現(xiàn)骨架屏效果。它提供了多種預定義的 SVG 形狀,可以快速生成骨架屏模板,并且可以自定義顏色、大小、動畫等。以下是在 Vue 3 中使用
vue-content-loader
實現(xiàn)骨架屏效果的步驟:
3.3.1.1 安裝和導入 vue-content-loader
在終端中使用 npm 安裝
vue-content-loader
:
npm install vue-content-loader
然后在需要使用的組件中導入 SkeletonLoader
組件:
import { SkeletonLoader } from 'vue-content-loader';
3.3.1.2 創(chuàng)建骨架屏模板
在模板中使用
SkeletonLoader
組件,并通過type
屬性指定要使用的 SVG 形狀。例如,要使用矩形形狀可以這樣寫:
<template> <div> <SkeletonLoader :width="300" :height="200" type="rect" /> </div> </template>
3.3.1.3 自定義骨架屏模板
可以通過
vue-content-loader
提供的屬性來自定義骨架屏模板的顏色、大小、動畫等。例如,要改變矩形形狀的顏色和大小可以這樣寫:
<template> <div> <SkeletonLoader :width="300" :height="200" type="rect" :rect="{ rx: 5, ry: 5 }" :speed="1" :primaryColor="'#f3f3f3'" :secondaryColor="'#ecebeb'" /> </div> </template>
在上面的代碼中,我們通過
rect
屬性設(shè)置了矩形的圓角半徑,通過speed
屬性設(shè)置了動畫速度,通過primaryColor
和secondaryColor
屬性設(shè)置了骨架屏的顏色。
以上就是在 Vue 3 中使用
vue-content-loader
實現(xiàn)骨架屏效果的基本步驟。需要注意的是,vue-content-loader
組件庫提供了多種預定義的 SVG 形狀,你可以根據(jù)需求選擇合適的形狀,并通過屬性來自定義骨架屏的樣式和動畫。
3.3.2 使用 vue-skeleton-webpack-plugin 實現(xiàn)骨架屏的示例
vue-skeleton-webpack-plugin
是一個 Webpack 插件,可以幫助我們在打包過程中生成骨架屏模板,并自動注入到 HTML 文件中。以下是使用
vue-skeleton-webpack-plugin
實現(xiàn)骨架屏的示例:
3.3.2.1 安裝和配置 vue-skeleton-webpack-plugin
在終端中使用 npm 安裝
vue-skeleton-webpack-plugin
:
npm install vue-skeleton-webpack-plugin
然后在 Vue 項目的 vue.config.js
文件中添加以下配置:
const VueSkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin'); module.exports = { configureWebpack: { plugins: [ new VueSkeletonWebpackPlugin({ webpackConfig: { entry: { app: './src/skeleton.js' // 指定骨架屏入口文件 } }, insertAfter: '<div id="app"></div>', // 骨架屏注入位置 minimize: true, quiet: true }) ] } };
在上面的示例中,我們指定了骨架屏的入口文件為 ./src/skeleton.js,并通過 insertAfter 屬性指定了注入位置。
3.3.2.2 創(chuàng)建骨架屏模板
在項目中創(chuàng)建骨架屏模板,可以使用 vue-content-loader 或其他骨架屏工具來生成模板。
例如,創(chuàng)建了一個 Skeleton.vue 組件來定義骨架屏模板:
<template> <div> <SkeletonLoader :width="300" :height="200" type="rect" :rect="{ rx: 5, ry: 5 }" :speed="1" :primaryColor="'#f3f3f3'" :secondaryColor="'#ecebeb'" /> </div> </template> <script> import { SkeletonLoader } from 'vue-content-loader'; export default { name: 'Skeleton', components: { SkeletonLoader } }; </script>
3.3.2.3 創(chuàng)建骨架屏入口文件
在項目中創(chuàng)建骨架屏入口文件
skeleton.js
,用于生成骨架屏模板。例如,在
skeleton.js
中創(chuàng)建了一個 Vue 實例,使用Skeleton
組件作為根組件:
import Vue from 'vue'; import Skeleton from './components/Skeleton.vue'; new Vue({ render: h => h(Skeleton) }).$mount('#app');
在上面的代碼中,通過
render
函數(shù)將Skeleton
組件渲染到 DOM 中的#app
元素上。
3.3.2.4 注入骨架屏模板到 HTML 文件中
在 HTML 文件中,使用
vue-skeleton-webpack-plugin
提供的Skeleton
標簽來注入骨架屏模板。例如,在
public/index.html
文件中添加以下代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>My App</title> </head> <body> <Skeleton></Skeleton> <div id="app"></div> </body> </html>
在上面的代碼中,我們在
Skeleton
標簽中注入了骨架屏模板,并將真實內(nèi)容放在app
標簽中。
3.3.2.5 打包項目并查看效果
在終端中運行以下命令打包項目:
npm run build
打包完成后,打開生成的
index.html
文件,即可看到骨架屏效果。在加載真實內(nèi)容之前,頁面會顯示骨架屏模板,提升用戶體驗。
3.4 代碼優(yōu)化
在代碼優(yōu)化時,需要綜合考慮多個方面,包括性能、可讀性、可維護性等。
下面是一些常見的代碼優(yōu)化方式及其結(jié)果問題:
- 懶加載/按需加載
- 緩存機制
- 代碼壓縮和合并
- 其他優(yōu)化方式
3.4.1 懶加載/按需加載
懶加載/按需加載是指將頁面或模塊的加載推遲到需要時再進行,以減少初始加載時間和網(wǎng)絡(luò)請求次數(shù),提高頁面性能。然而,在使用懶加載/按需加載時,可能會出現(xiàn)以下問題:
- 首次加載時,用戶可能需要等待更長時間才能看到頁面內(nèi)容。
- 如果按需加載的模塊過多,可能會出現(xiàn)過多的網(wǎng)絡(luò)請求,導致頁面加載速度變慢。
- 懶加載/按需加載的代碼可能會增加復雜度,降低代碼的可讀性和可維護性。
3.4.2 緩存機制
緩存機制是指將一些靜態(tài)資源(如圖片、CSS、JS 等)緩存在客戶端,以減少網(wǎng)絡(luò)請求次數(shù),提高頁面性能。然而,在使用緩存機制時,可能會出現(xiàn)以下問題:
- 如果緩存時間過長,可能會導致用戶無法看到最新的內(nèi)容。
- 如果緩存時間過短,可能會導致用戶頻繁地重新請求資源,降低頁面性能。
- 緩存機制可能會對服務器和客戶端產(chǎn)生額外的負擔,增加服務器和客戶端的開銷。
3.4.3 代碼壓縮和合并
代碼壓縮和合并是指將多個 JS 或 CSS 文件壓縮為一個文件,并將其中的空格、注釋等無關(guān)字符刪除,以減小文件大小,提高頁面性能。然而,在使用代碼壓縮和合并時,可能會出現(xiàn)以下問題:
- 如果壓縮和合并的文件過大,可能會導致文件下載時間過長,影響頁面性能。
- 代碼壓縮和合并可能會增加復雜度,降低代碼的可讀性和可維護性。
- 如果壓縮和合并的文件不夠靈活,可能會導致無法對不同的頁面進行定制和優(yōu)化。
3.4.4 其他優(yōu)化方式
除了上述方式外,還有一些其他的代碼優(yōu)化方式,如使用更高效的算法或數(shù)據(jù)結(jié)構(gòu)、減少重繪和回流、優(yōu)化圖片大小和格式等。這些優(yōu)化方式的效果和問題也各不相同,需要根據(jù)具體情況進行選擇和評估。
綜上所述,代碼優(yōu)化需要綜合考慮多個方面,不能只追求性能,還要注意代碼的可讀性和可維護性,以確保代碼質(zhì)量和用戶體驗的均衡。
3.4.5 示例
下面是一個代碼優(yōu)化前后的示例對比:
假設(shè)有一個需求,需要在頁面上顯示一組商品列表,每個商品包含圖片、標題、描述、價格等信息。
可以使用 Vue.js 來實現(xiàn)該需求,如下所示:
<template> <div> <h2>商品列表</h2> <ul> <li v-for="(item, index) in items" :key="index"> <img :src="item.image" :alt="item.title"> <h3>{{ item.title }}</h3> <p>{{ item.description }}</p> <span>¥{{ item.price }}</span> </li> </ul> </div> </template> <script> export default { data() { return { items: [] }; }, created() { fetch('https://api.example.com/products') .then(response => response.json()) .then(data => { this.items = data; }); } }; </script>
在上面的代碼中,使用了 Vue.js 的模板語法來創(chuàng)建商品列表,并通過
fetch
方法從后端 API 獲取商品數(shù)據(jù)。然而,在實際應用中,該代碼存在一些性能問題,可以進行優(yōu)化。
下面是一個針對該代碼的優(yōu)化方案:
<template> <div> <h2>商品列表</h2> <ul> <li v-for="(item, index) in items" :key="index"> <img :src="item.image" :alt="item.title"> <h3>{{ item.title }}</h3> <p>{{ item.description }}</p> <span>¥{{ item.price }}</span> </li> </ul> </div> </template> <script> import axios from 'axios'; export default { data() { return { items: [], loading: true }; }, async created() { try { const response = await axios.get('https://api.example.com/products'); this.items = response.data; } catch (error) { console.error(error); } finally { this.loading = false; } } }; </script>
在上面的優(yōu)化方案中,使用了以下優(yōu)化方式:
- 使用
axios
替換fetch
,以提高網(wǎng)絡(luò)請求的穩(wěn)定性和可讀性。- 將
created
鉤子函數(shù)改為異步函數(shù),并使用async/await
語法簡化異步代碼,以提高代碼可讀性。- 添加
loading
變量,用于在數(shù)據(jù)加載完成前顯示加載動畫,以提高用戶體驗。通過以上優(yōu)化,可以提高代碼的性能、可讀性和可維護性,從而提高應用的質(zhì)量和用戶體驗。
3.5 如何設(shè)置瀏覽器緩存策略以提高頁面加載速度?
設(shè)置瀏覽器緩存策略可以減少瀏覽器重復請求資源,從而提高頁面加載速度??梢酝ㄟ^在 HTTP 響應頭中設(shè)置緩存策略來實現(xiàn)。
以下是一些常見的緩存策略設(shè)置方法:
- 設(shè)置強緩存
- 設(shè)置協(xié)商緩存
3.5.1 設(shè)置強緩存
強緩存是指瀏覽器在一定時間內(nèi)直接從本地緩存中獲取資源,而不需要向服務器發(fā)送請求。可以通過設(shè)置 "Expires" 或者 "Cache-Control" 響應頭來設(shè)置強緩存時間,如下所示:
- Expires:設(shè)置過期時間,例如 "Expires: Wed, 21 Oct 2023 07:28:00 GMT"
- Cache-Control:設(shè)置緩存策略,例如 "Cache-Control: max-age=3600",表示資源在 3600 秒內(nèi)有效。
3.5.2 設(shè)置協(xié)商緩存
協(xié)商緩存是指瀏覽器在過期時間后,向服務器發(fā)送請求,服務器會根據(jù)資源的 ETag 或者 Last-Modified 等信息,判斷資源是否發(fā)生變化。如果資源沒有發(fā)生變化,服務器會返回 304 狀態(tài)碼,告訴瀏覽器可以直接使用本地緩存。可以通過設(shè)置 "Last-Modified" 和 "ETag" 響應頭來設(shè)置協(xié)商緩存,如下所示:
- Last-Modified:表示資源的最后修改時間,例如 "Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT"
- ETag:表示資源的唯一標識符,例如 "ETag: W/1234567890"
注意,設(shè)置緩存策略時需要根據(jù)具體情況進行設(shè)置,過長的緩存時間可能會導致資源更新不及時,而過短的緩存時間則可能會影響頁面加載速度。建議根據(jù)實際情況進行調(diào)整。
以上就是VUE解決圖片視頻加載緩慢/首屏加載白屏的問題的詳細內(nèi)容,更多關(guān)于VUE圖片視頻加載緩慢/首屏加載白屏的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue實現(xiàn)的網(wǎng)易云音樂在線播放和下載功能案例
這篇文章主要介紹了vue實現(xiàn)的網(wǎng)易云音樂在線播放和下載功能,結(jié)合具體實例形式分析了網(wǎng)易云音樂相關(guān)接口調(diào)用與操作技巧,需要的朋友可以參考下2019-02-02vue實現(xiàn)動態(tài)監(jiān)測元素高度
這篇文章主要介紹了vue實現(xiàn)動態(tài)監(jiān)測元素高度方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10vue.nextTick()與setTimeout的區(qū)別及說明
這篇文章主要介紹了vue.nextTick()與setTimeout的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03