Vue 3瀑布流組件實現詳解 - 圖片展示方案

引言:瀑布流布局的魅力與應用場景

在當今富媒體內容主導的網絡環境中,瀑布流布局已成為展示圖片商品等內容的流行方式。它通過動態布局算法在有限空間內最大化內容展示,提供視覺連續性流暢瀏覽體驗。本文將深入探討如何使用Vue 3實現一個功能完備的瀑布流組件,并解決圖片懶加載等關鍵問題。

瀑布流組件核心實現

1. 組件設計思路

我們的瀑布流組件解決了以下關鍵問題:

  • 響應式布局:根據容器寬度自動調整列數
  • 高效圖片加載:支持懶加載和預加載模式
  • 視覺優化:平滑的位置過渡動畫
  • 錯誤處理:優雅的加載失敗處理機制
  • 高定制性:通過插槽支持自定義內容

2. 核心算法實現

列數與列寬計算
const calculateColumns = () => {wrapperWidth.value = waterfallWrapper.value.clientWidth;// 響應式斷點處理const sortedBreakpoints = Object.keys(props.breakpoints).map(Number).sort((a, b) => b - a);// 根據斷點確定列數for (const breakpoint of sortedBreakpoints) {if (wrapperWidth.value >= breakpoint) {cols.value = props.breakpoints[breakpoint].rowPerView;break;}}// 計算列寬(考慮間距和對齊方式)if (props.hasAroundGutter) {colWidth.value = (wrapperWidth.value - props.gutter * 2 - (cols.value - 1) * props.gutter) / cols.value;offsetX.value = props.gutter;} else {colWidth.value = (wrapperWidth.value - (cols.value - 1) * props.gutter) / cols.value;offsetX.value = 0;}// 處理對齊方式if (props.align === 'center') {const totalWidth = cols.value * colWidth.value + (cols.value - 1) * props.gutter;offsetX.value = (wrapperWidth.value - totalWidth) / 2;} else if (props.align === 'right') {const totalWidth = cols.value * colWidth.value + (cols.value - 1) * props.gutter;offsetX.value = wrapperWidth.value - totalWidth;}
};
瀑布流布局算法
const calculateLayout = () => {const columnHeights = new Array(cols.value).fill(0);let maxHeight = 0;items.forEach((item, index) => {// 尋找高度最小的列let minColHeight = columnHeights[0];let colIndex = 0;for (let i = 1; i < cols.value; i++) {if (columnHeights[i] < minColHeight) {minColHeight = columnHeights[i];colIndex = i;}}// 計算元素位置const x = colIndex * (colWidth.value + props.gutter) + offsetX.value;const y = columnHeights[colIndex];// 應用位置變換item.style.transform = `translate3d(${x}px, ${y}px, 0)`;item.style.width = `${colWidth.value}px`;// 更新列高度const itemHeight = item.offsetHeight || 200;columnHeights[colIndex] += itemHeight + props.gutter;// 更新容器高度if (columnHeights[colIndex] > maxHeight) {maxHeight = columnHeights[colIndex];}});wrapperHeight.value = maxHeight;
};

3. 高級功能實現

智能圖片懶加載
const initLazyLoad = () => {observer.value = new IntersectionObserver((entries) => {entries.forEach(entry => {if (entry.isIntersecting) {const img = entry.target;// 設置loading占位圖if (props.loadingImg) img.src = props.loadingImg;// 延遲加載實際圖片setTimeout(() => {loadImage(img);// 圖片加載完成觸發布局更新img.onload = () => debouncedLayout();// 錯誤處理if (props.errorImg) {img.onerror = () => {img.src = props.errorImg;debouncedLayout(); // 錯誤時也更新布局};}img.removeAttribute('data-src');}, props.delay);observer.value.unobserve(img);}});}, { threshold: 0.01 });// 觀察所有懶加載圖片const lazyImages = waterfallWrapper.value.querySelectorAll('img[data-src]');lazyImages.forEach(img => observer.value.observe(img));
};
防抖優化性能
const debounce = (fn, delay) => {let timeoutId;return (...args) => {clearTimeout(timeoutId);timeoutId = setTimeout(() => fn.apply(this, args), delay);};
};// 使用防抖優化布局計算
const debouncedLayout = debounce(() => {calculateColumns();calculateLayout();
}, props.posDuration);

性能優化策略

  1. GPU加速動畫

    .waterfall-item {transition: transform 0.3s ease;will-change: transform;
    }
    
  2. 智能加載策略

    • 優先加載視口內圖片
    • 設置加載延遲避免卡頓
    • 使用占位圖保持布局穩定
  3. 高效的事件處理

    onMounted(() => {window.addEventListener('resize', debouncedLayout);
    });onUnmounted(() => {window.removeEventListener('resize', debouncedLayout);if (observer.value) observer.value.disconnect();
    });
    
  4. 響應式斷點設計

    breakpoints: {1200: { rowPerView: 4 },800: { rowPerView: 3 },500: { rowPerView: 2 }
    }
    

常見問題解決方案

  1. 圖片加載導致布局抖動問題

    • 使用固定比例的占位圖容器
    • 預先設置圖片尺寸屬性
    • 添加加載過渡動畫
  2. 白屏問題處理

    // 確保初始渲染可見
    nextTick(() => {calculateColumns();calculateLayout();
    });
    
  3. 大量數據性能優化

    • 虛擬滾動技術
    • 分頁加載
    • 回收不可見DOM節點

總結

通過本文,我們實現了一個高性能可定制的Vue 3瀑布流組件,它具有以下特點:

  1. 智能化布局:自動計算最佳列數和位置
  2. 多種加載模式:支持懶加載和預加載
  3. 響應式設計:完美適配不同屏幕尺寸
  4. 優雅的錯誤處理:提供自定義占位圖
  5. 平滑動畫:GPU加速的位置過渡效果

插件完整代碼

<template><div ref="waterfallWrapper" class="waterfall-list" :style="{ height: `${wrapperHeight}px` }"><div v-for="(item, index) in list" :key="getKey(item, index)" class="waterfall-item"><slot name="item" :item="item" :index="index" :url="getRenderURL(item)" /></div></div>
</template><script>
import { ref, watch, onMounted, onUnmounted, provide, nextTick } from "vue";export default {name: 'WaterfallList',props: {list: {type: Array,required: true,default: () => []},rowKey: {type: String,default: "id"},imgSelector: {type: String,default: "src"},width: {type: Number,default: 200},breakpoints: {type: Object,default: () => ({1200: { rowPerView: 4 },800: { rowPerView: 3 },500: { rowPerView: 2 }})},gutter: {type: Number,default: 10},hasAroundGutter: {type: Boolean,default: true},posDuration: {type: Number,default: 300},align: {type: String,default: "center",validator: (value) => ['left', 'center', 'right'].includes(value)},lazyLoad: {type: Boolean,default: true},crossOrigin: {type: Boolean,default: true},delay: {type: Number,default: 300},loadingImg: {type: String,default: ''},errorImg: {type: String,default: ''}},setup(props, { emit }) {const waterfallWrapper = ref(null);const wrapperWidth = ref(0);const colWidth = ref(0);const cols = ref(0);const offsetX = ref(0);const wrapperHeight = ref(0);const observer = ref(null);// 計算列數和列寬const calculateColumns = () => {if (!waterfallWrapper.value) return;wrapperWidth.value = waterfallWrapper.value.clientWidth;// 根據斷點確定列數const sortedBreakpoints = Object.keys(props.breakpoints).map(Number).sort((a, b) => b - a); // 從大到小排序let foundCols = 1;for (const breakpoint of sortedBreakpoints) {if (wrapperWidth.value >= breakpoint) {foundCols = props.breakpoints[breakpoint].rowPerView;break;}}cols.value = foundCols;// 計算列寬if (props.hasAroundGutter) {colWidth.value = (wrapperWidth.value - props.gutter * 2 - (cols.value - 1) * props.gutter) / cols.value;offsetX.value = props.gutter;} else {colWidth.value = (wrapperWidth.value - (cols.value - 1) * props.gutter) / cols.value;offsetX.value = 0;}// 處理對齊方式if (props.align === 'center') {const totalWidth = cols.value * colWidth.value + (cols.value - 1) * props.gutter;offsetX.value = (wrapperWidth.value - totalWidth) / 2;} else if (props.align === 'right') {const totalWidth = cols.value * colWidth.value + (cols.value - 1) * props.gutter;offsetX.value = wrapperWidth.value - totalWidth;}};// 加載圖片const loadImage = (img) => {const url = img.dataset?.src || img.getAttribute('data-src');if (url) {// 創建臨時Image對象預加載const tempImage = new Image();tempImage.onload = () => {img.src = url;if (props.crossOrigin) img.crossOrigin = 'anonymous';img.removeAttribute('data-src');debouncedLayout(); // 關鍵:加載完成后觸發布局更新};tempImage.onerror = () => {if (props.errorImg) img.src = props.errorImg;img.removeAttribute('data-src');debouncedLayout(); // 關鍵:加載失敗時也觸發布局更新};tempImage.src = url;return true;}return false;};// 加載所有圖片(修改后)const loadAllImages = () => {if (!waterfallWrapper.value) return;const images = waterfallWrapper.value.querySelectorAll('img[data-src]');images.forEach(img => {// 設置loading占位圖if (props.loadingImg) img.src = props.loadingImg;// 加載實際圖片并監聽加載完成事件const loaded = loadImage(img);// 錯誤處理if (loaded && props.errorImg) {img.onerror = () => {img.src = props.errorImg;debouncedLayout(); // 關鍵:錯誤時也觸發布局更新};}});};// const loadAllImages = () => {//   if (!waterfallWrapper.value) return;//   const images = waterfallWrapper.value.querySelectorAll('img');//   images.forEach(img => {//     // 如果已經是加載狀態則跳過//     if (img.src && !img.src.includes(props.loadingImg)) return;//     // 嘗試加載圖片//     const loaded = loadImage(img);//     // 設置錯誤處理//     if (loaded && props.errorImg) {//       img.onerror = () => {//         img.src = props.errorImg;//       };//     }//   });// };// 初始化懶加載const initLazyLoad = () => {if (!waterfallWrapper.value) return;// 清理舊的觀察器if (observer.value) {observer.value.disconnect();}// 創建新的觀察器observer.value = new IntersectionObserver((entries) => {entries.forEach(entry => {if (entry.isIntersecting) {const img = entry.target;if (img.dataset?.src || img.getAttribute('data-src')) {// 設置loading占位圖if (props.loadingImg) {img.src = props.loadingImg;}// 延遲加載實際圖片setTimeout(() => {loadImage(img);img.onload = () => debouncedLayout();if (props.errorImg) {img.onerror = () => {img.src = props.errorImg;};}// 移除data-src屬性img.removeAttribute('data-src');}, props.delay);}observer.value.unobserve(img);}});}, { threshold: 0.01 });// 觀察所有懶加載圖片const lazyImages = waterfallWrapper.value.querySelectorAll('img[data-src]');lazyImages.forEach(img => {observer.value.observe(img);});};// 計算布局const calculateLayout = () => {if (!waterfallWrapper.value || cols.value === 0) return;const items = waterfallWrapper.value.querySelectorAll('.waterfall-item');if (items.length === 0) return;const columnHeights = new Array(cols.value).fill(0);let maxHeight = 0;items.forEach((item, index) => {let minColHeight = columnHeights[0];let colIndex = 0;for (let i = 1; i < cols.value; i++) {if (columnHeights[i] < minColHeight) {minColHeight = columnHeights[i];colIndex = i;}}const x = colIndex * (colWidth.value + props.gutter) + offsetX.value;const y = columnHeights[colIndex];item.style.transform = `translate3d(${x}px, ${y}px, 0)`;item.style.width = `${colWidth.value}px`;item.style.position = 'absolute';item.style.left = '0';item.style.top = '0';item.style.visibility = 'visible';// 計算項目高度(包含所有圖片)const itemHeight = item.offsetHeight || 200;columnHeights[colIndex] += itemHeight + props.gutter;// 更新最大高度if (columnHeights[colIndex] > maxHeight) {maxHeight = columnHeights[colIndex];}});wrapperHeight.value = maxHeight;emit('afterRender');};// 防抖函數const debounce = (fn, delay) => {let timeoutId;return (...args) => {clearTimeout(timeoutId);timeoutId = setTimeout(() => fn.apply(this, args), delay);};};const debouncedLayout = debounce(() => {calculateColumns();calculateLayout();}, props.posDuration);// 初始化onMounted(() => {if (!waterfallWrapper.value) return;calculateColumns();nextTick(() => {if (props.lazyLoad) {initLazyLoad();} else {loadAllImages(); // 非懶加載模式直接加載圖片}calculateLayout(); // 初始布局});window.addEventListener('resize', debouncedLayout);});// 清理onUnmounted(() => {if (observer.value) {observer.value.disconnect();}window.removeEventListener('resize', debouncedLayout);});// 監聽數據變化(修改部分)watch(() => props.list, () => {debouncedLayout();nextTick(() => {if (props.lazyLoad) {initLazyLoad();} else {// 延遲加載確保DOM更新完成setTimeout(loadAllImages, 0);}});}, { deep: true });// 提供刷新方法provide('refreshWaterfall', debouncedLayout);const getRenderURL = (item) => {return item[props.imgSelector];};const getKey = (item, index) => {return item[props.rowKey] || index;};return {waterfallWrapper,wrapperHeight,getRenderURL,getKey};}
};
</script><style scoped>
.waterfall-list {position: relative;width: 100%;margin: 0 auto;
}.waterfall-item {position: absolute;visibility: hidden;transition: transform 0.3s ease;will-change: transform;box-sizing: border-box;
}
</style>

調用示例

<template><div class="container"><h1>圖片瀑布流懶加載示例</h1><!-- 瀑布流組件 --><waterfall-list :list="imageList" :lazy-load="false" :cross-origin="true" :delay="300"loading-img="https://via.placeholder.com/300x200?text=Loading..."error-img="https://via.placeholder.com/300x200?text=Error" :width="300" :gutter="15" @afterRender="onAfterRender"><template #item="{ item, url }"><div class="image-card"><!-- 使用data-src實現懶加載 --><img :data-src="url" :alt="item.title" class="image" @load="onImageLoad" /><div class="info"><h3>{{ item.title }}</h3><p>{{ item.description }}</p></div></div></template></waterfall-list><!-- 加載更多按鈕 --><button class="load-more" @click="loadMoreImages" :disabled="isLoading">{{ isLoading ? '加載中...' : '加載更多' }}</button></div>
</template><script>
import { ref } from 'vue';
import WaterfallList from '../components/vWaterfall.vue'; // 根據實際路徑調整export default {components: {WaterfallList},setup() {// 模擬圖片數據const generateImages = (count, startIndex = 0) => {return Array.from({ length: count }, (_, i) => ({id: startIndex + i,title: `圖片 ${startIndex + i + 1}`,description: `這是第 ${startIndex + i + 1} 張圖片的描述`,src: `https://picsum.photos/id/${startIndex + i + 10}/300/200`}));};const imageList = ref(generateImages(12));const isLoading = ref(false);// 圖片加載完成回調const onImageLoad = (e) => {console.log('圖片加載完成', e.target);};// 瀑布流渲染完成回調const onAfterRender = () => {console.log('瀑布流布局完成');};// 加載更多圖片const loadMoreImages = () => {isLoading.value = true;setTimeout(() => {const newImages = generateImages(6, imageList.value.length);imageList.value = [...imageList.value, ...newImages];isLoading.value = false;}, 1000);};return {imageList,isLoading,onImageLoad,onAfterRender,loadMoreImages};}
};
</script><style scoped>
.container {max-width: 1200px;margin: 0 auto;padding: 20px;
}h1 {text-align: center;margin-bottom: 30px;color: #333;
}.image-card {background: #fff;border-radius: 8px;overflow: hidden;box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);transition: transform 0.3s ease;
}.image-card:hover {transform: translateY(-5px);
}.image {width: 100%;height: auto;display: block;background: #f5f5f5;transition: opacity 0.3s ease;
}.info {padding: 15px;
}.info h3 {margin: 0 0 8px 0;font-size: 16px;color: #333;
}.info p {margin: 0;font-size: 14px;color: #666;
}.load-more {display: block;width: 200px;margin: 30px auto;padding: 12px 24px;background: #4a8cff;color: white;border: none;border-radius: 4px;font-size: 16px;cursor: pointer;transition: background 0.3s ease;
}.load-more:hover {background: #3a7be0;
}.load-more:disabled {background: #ccc;cursor: not-allowed;
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84507.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84507.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84507.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何確保郵件內容符合反垃圾郵件規范?

一、遵守相關法規 美國《CAN-SPAM法案》規定&#xff0c;郵件頭信息必須真實準確&#xff0c;要標明廣告性質、提供有效地址&#xff0c;并在 10 個工作日內響應退訂請求。 歐盟《通用數據保護條例》&#xff08;GDPR&#xff09;強調獲得用戶明確同意&#xff0c;數據使用要…

MQ解決高并發下訂單問題,實現流量削峰

文章目錄 示例&#xff1a;電商秒殺系統中的流量削峰1. 依賴引入&#xff08;Maven&#xff09;2. 消息隊列配置&#xff08;RabbitMQ&#xff09;3. 生產者&#xff1a;訂單服務&#xff08;接收高并發請求&#xff09;4. 消費者&#xff1a;庫存服務&#xff08;按系統容量處…

【二進制安全作業】250616課上作業2 - 棧溢出漏洞利用

文章目錄 前言一、使用環境二、程序源碼1. C語言源碼2. 編譯方式 三、源碼分析四、反匯編分析1. 檢查文件安全性2. 查找目標函數3. 計算偏移量4. 繞過 strlen5. 繞過 if 五、編寫EXP結語 前言 直接進入正題 一、使用環境 處理器架構&#xff1a;x86_64 操作系統&#xff1a;U…

Python類型處理與推導式

歡迎來到啾啾的博客&#x1f431;。 記錄學習點滴。分享工作思考和實用技巧&#xff0c;偶爾也分享一些雜談&#x1f4ac;。 有很多很多不足的地方&#xff0c;歡迎評論交流&#xff0c;感謝您的閱讀和評論&#x1f604;。 目錄 1 引言2 類型處理3 高效操作AI開發常見數據結構3…

數據庫char字段做trim之后查詢很慢的解決方式

select * from TABLE0 where trim(column1):param 當表數據量大時&#xff0c;即使給column1字段加上索引&#xff0c;這條查詢語句也會很慢。 因為使用trim函數后&#xff0c;column1的索引會失效&#xff0c;有兩種處理方法&#xff1a; 1.給表加上trim(column1)函數索引 …

Kafka核心架構解析:從CAP理論到消息可靠性的設計哲學

摘要 本文從分布式系統CAP理論和消息可靠性兩個視角深入解析Kafka的架構設計&#xff0c;通過概念關系圖和組件交互圖揭示其核心設計思想&#xff0c;并詳細拆解各組件功能與協作機制。文章包含完整的交互流程分析和配置參數說明&#xff0c;是理解Kafka設計精髓的實用指南。 一…

LeetCode 275.H指數 II

題目&#xff1a; 給你一個整數數組 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇論文被引用的次數&#xff0c;citations 已經按照 非降序排列 。計算并返回該研究者的 h 指數。 h 指數的定義&#xff1a;h 代表“高引用次數”&#xff08;high citations&…

OV汽車攝像頭cmos sensor 相關情況介紹

OV汽車攝像頭cmos sensor 相關情況介紹 文章目錄 OV汽車攝像頭cmos sensor 相關情況介紹**1. 汽車攝像頭三大場景應用****2. 車載CMOS SENSOR的核心技術****3. 兩大車規認證:實現真正的車規可靠性****4. 最新產品**2022年,汽車智能化加碼提速,被譽為“智能駕駛之眼”的車載攝…

Pinia在多步驟表單中的實踐應用

引言 Pinia是Vue 3推薦的狀態管理庫&#xff0c;相比Vuex提供了更簡潔的API、更好的TypeScript支持和更靈活的組合式風格。本文基于實際項目代碼&#xff0c;詳細介紹Pinia在多步驟表單場景中的應用方法。 1. Pinia Store的創建與設計 1.1 基礎Store結構 在src/store/modul…

目標檢測之YOLOV11的環境搭建

1 創建虛擬環境 conda create -n yolov11 python3.9 conda activate yolov112 安裝ultralytics 默認是有cuda的情況下 # Install all packages together using conda conda install pytorch torchvision conda 還不能直接安裝ultralytics&#xff0c;需要通過pip進行安裝 …

Android 構建配置中的變量(通常在設備制造商或定制 ROM 的 AndroidProducts.mk 或產品配置文件中定義)

以下是 Android 構建系統中常見的用于產品配置、資源復制和構建規則的變量 1. PRODUCT_COPY_FILES 作用&#xff1a;指定需要從源碼樹復制到鏡像的文件。示例&#xff1a;PRODUCT_COPY_FILES \device/manufacturer/device_name/file.conf:$(TARGET_COPY_OUT_VENDOR)/etc/file…

火山引擎項亮:機器學習與智能推薦平臺多云部署解決方案正式發布

資料來源&#xff1a;火山引擎-開發者社區 2022年7月20日&#xff0c;火山引擎2022 Force原動力大會在北京諾金酒店成功舉辦。在上午的議程中&#xff0c;《推薦系統實踐》一書的作者、同時也是火山引擎機器學習系統負責人——項亮&#xff0c;展開了題目為《開放AI基建&#x…

NVR的方法多種取決于應用場景

攝像頭接入NVR&#xff08;網絡視頻錄像機&#xff09;的方法通常取決于具體的應用場景和設備支持的功能。 一、通過局域網接入 設備連接 &#xff1a; 將攝像機通過網絡線纜連接到NVR的對應端口&#xff0c;或者將攝像機和NVR都連接到同一個路由器/交換機上&#xff0c;確保它…

JAVA從入門到精通一文搞定

博主介紹&#xff1a; 大家好&#xff0c;我是想成為Super的Yuperman&#xff0c;互聯網宇宙廠經驗&#xff0c;17年醫療健康行業的碼拉松奔跑者&#xff0c;曾擔任技術專家、架構師、研發總監負責和主導多個應用架構。 近期專注&#xff1a; DeepSeek應用&#xff0c;RPA應用研…

火山引擎發布大模型生態廣場MCP Servers,LAS MCP助力AI數據湖構建

資料來源&#xff1a;火山引擎-開發者社區 近日&#xff0c;火山引擎發布大模型生態廣場—— MCP Servers&#xff0c;借助字節跳動生態能力&#xff0c;通過“MCP Market&#xff08;工具廣場&#xff09; 火山方舟&#xff08;大模型服務&#xff09;Trae&#xff08;應用開…

NodeJS 對接 Outlook 發信服務器實現發信功能

示例代碼&#xff1a; const express require(express); const nodemailer require(nodemailer); const querystring require(querystring); const axios require(axios);const app express(); app.use(express.json());const transporter nodemailer.createTransport({…

【同聲傳譯】RealtimeSTT:超低延遲語音轉文字,支持喚醒詞與中譯英

把你說的話實時變成文字&#xff1a;RealtimeSTT 上手體驗 想找一個真正好用的語音轉文字工具嗎&#xff1f;不用等說完一整段才出結果&#xff0c;也不用反復點擊按鈕。RealtimeSTT 這個開源項目能做到??實時??轉錄&#xff0c;你說一句&#xff0c;屏幕上幾乎同時出現文…

【大模型lora微調】關于推理時如何使用 LoRA Adapter

假設你有兩部分&#xff1a; 一個是原始大模型&#xff08;base model&#xff09; 一個是保存的 LoRA Adapter&#xff08;adapter_config.json adapter_model.bin&#xff09; 不合并的情況下推理方法 你可以用 peft 的方式加載 LoRA Adapter&#xff0c;推理時這樣寫&a…

谷歌時間序列算法:零樣本預測如何重塑行業決策?

谷歌時間序列算法&#xff1a;零樣本預測如何重塑行業決策&#xff1f; TimesFM 你是否曾面臨這樣的困境&#xff1f;—— ? 需要預測新產品銷量&#xff0c;卻苦于缺乏歷史數據&#xff1b; ? 依賴傳統模型&#xff08;如ARIMA&#xff09;&#xff0c;但調參耗時且泛化能力…

國產服務器【銀河麒麟v10】【CPU鯤鵬920】部署Minio文件服務器

目錄 準備工作操作步驟1. 確認掛載點狀態2. 創建專用用戶和目錄3. 下載ARM版Minio到掛在盤4. 環境變量配置5. 更新Systemd服務配置6. 啟動、重啟7. 防火墻8. 訪問驗證9. 故障排查&#xff08;如服務未啟動&#xff09;? 結束 準備工作 環境要求&#xff1a;Linux虛擬機 操作…