:基于 DropZone 與 FilePicker 的 ZIP 文件上傳區(qū)域)
wp-calypso Upload Drop Zone 組件實戰(zhàn)基于 DropZone 與 FilePicker 的 ZIP 文件上傳區(qū)域【免費下載鏈接】wp-calypsoThe JavaScript and API powered WordPress.com項目地址: https://gitcode.com/gh_mirrors/wp/wp-calypsoUpload Drop Zone 是 wp-calypso 中一個將“拖拽放置區(qū)drop-zone”與“文件選擇器file-picker”合二為一的復合組件專門用于上傳 ZIP 壓縮包用戶既可以點擊區(qū)域打開系統(tǒng)文件瀏覽器也可以直接把單個 zip 文件拖拽到區(qū)域上完成上傳。閱讀本文后你將掌握該組件的 Props 契約、內部校驗與錯誤處理邏輯理解它如何復用 DropZone 與 FilePicker 兩個底層基礎組件并能參照 主題上傳頁面 的真實集成方式在自己的業(yè)務界面中落地使用。組件定位拖拽與點擊二合一的上傳入口組件源碼位于 client/blocks/upload-drop-zone由三個文件組成index.jsx組件實現(xiàn)、style.scss樣式、README.md文檔。按官方 README 的定義A combined drop-zone and filepicker for uploading zip files. Click to open a file browser, or drop a single zip file onto it. Accepts a function that will be called with the selected file.它的核心定位可以拆解為三點一種交互、兩種入口點擊區(qū)域彈出文件選擇器或將文件拖拽到區(qū)域上最終走同一條doUpload回調面向 ZIP 場景文件選擇器通過acceptapplication/zip限定可選類型并提示“Only single .zip files are accepted.”單個文件約束內部強制只接受單個 zip 文件多文件、超大文件都會被攔截并給出錯誤提示??焖偕鲜肿钚〗尤胧纠凑?README 提供的用法接入方式非常簡潔——只需要向組件傳入一個處理上傳的函數(shù)function render() { const doUpload this.props.uploadTheme; return UploadDropZone doUpload{ doUpload } /; }從源碼實現(xiàn)看doUpload的實際簽名是doUpload( siteId, file )其中siteId由組件內部通過 Redux 自動注入詳見下文 Props 說明業(yè)務方只需關注拿到File對象后如何處理即可。Props 契約詳解doUpload必需屬性值TypeFunctionRequiredYes在 index.jsx 中doUpload被聲明為PropTypes.func.isRequired。README 明確說明它接收siteId和File兩個參數(shù)當用戶選中拖入或點選一個 zip 文件后即被調用。disabled可選屬性值TypeBooleanRequiredNo設為true時禁用整個選擇器與放置區(qū)。禁用狀態(tài)在視覺上由 style.scss 通過is-disabled類實現(xiàn)opacity: 0.2降低透明度pointer-events: none阻斷所有鼠標交互同時該狀態(tài)也會透傳給底層的DropZonedisabledprop使其不再響應拖拽事件。源碼中暴露的額外 PropsREADME 未列出但可用onFileTooLargeFunction可選當用戶選擇的文件超過大小上限時若提供了此回調則優(yōu)先調用它未提供時組件會自行彈出錯誤提示見下文“文件校驗”小節(jié)。siteIdnumber自動注入通過connect從getSelectedSiteId( state )獲取因此業(yè)務方通常不需要手動傳遞。交互流程與內部實現(xiàn)剖析組件的完整交互鏈路在 index.jsx 中實現(xiàn)核心是onFileSelect處理器onFileSelect ( files ) { const { translate, siteId, doUpload } this.props; if ( files.length ! 1 ) { this.props.errorNotice( translate( Please drop a single zip file ) ); return; } // DropZone supplies an array, FilePicker supplies a FileList const file files[ 0 ] || files.item( 0 ); if ( file.size MAX_UPLOAD_ZIP_SIZE ) { if ( this.props.onFileTooLarge ) { this.props.onFileTooLarge(); } else { this.props.errorNotice( translate( Zip file is too large. Please upload a file under %(maxSize)d MB., { args: { maxSize: Math.floor( MAX_UPLOAD_ZIP_SIZE / 1000000 ) }, } ) ); } return; } doUpload( siteId, file ); };數(shù)據(jù)源歸一化這里有一個值得注意的兼容性細節(jié)DropZone的onFilesDrop回調傳遞的是數(shù)組而FilePicker的onPick回調傳遞的是FileList。組件用files[ 0 ] || files.item( 0 )同時兼容兩種數(shù)據(jù)結構這也是onFileSelect能被兩個入口共用的前提。文件校驗數(shù)量校驗files.length ! 1時直接彈出“Please drop a single zip file”拒絕多文件上傳大小校驗MAX_UPLOAD_ZIP_SIZE定義于 client/lib/automated-transfer/constants.js值為50 * 1000000即50MB。超過上限時優(yōu)先觸發(fā)onFileTooLarge回調否則通過errorNotice展示“Zip file is too large. Please upload a file under 50 MB.”的錯誤提示。渲染結構return ( div className{ className } div classNameupload-drop-zone__dropzone DropZone onFilesDrop{ this.onFileSelect } disabled{ disabled } / FilePicker acceptapplication/zip onPick{ this.onFileSelect } Gridicon classNameupload-drop-zone__icon iconcloud-upload size{ 48 } / { dropText } span classNameupload-drop-zone__instructions{ uploadInstructionsText }/span /FilePicker /div /div );界面文案由 i18n 翻譯函數(shù)生成主文案為“Drop files or click here to install”輔助說明為“Only single .zip files are accepted.”。整個上傳區(qū)塊由DropZone負責拖拽放置和FilePicker負責點擊選擇疊加構成二者共享onFileSelect回調。底層基礎組件機制Upload Drop Zone 并非從零實現(xiàn)拖拽邏輯而是組合了兩個可復用的基礎組件理解它們有助于排查問題與二次開發(fā)。DropZone拖拽放置區(qū)client/components/drop-zone/index.jsx 是一個全局事件驅動的拖拽區(qū)域在componentDidMount中向window注冊dragover、drop、dragenter、dragleave、mouseup事件監(jiān)聽見 L44-L51并在卸載時逐一移除通過dragEnterNodes集合與MutationObserver追蹤拖拽目標節(jié)點以判斷文件是否正在頁面上拖拽見 toggleMutationObserveronDrop中除了觸發(fā)onFilesDrop( Array.prototype.slice.call( event.dataTransfer.files ) )外還會preventDefault阻止瀏覽器默認的“打開文件”行為并處理了 Safari 從 Dock 直接拖文件的兼容問題見 L163-L189支持fullScreen全屏放置模式此時通過RootChild渲染到根節(jié)點并允許通過CustomEvent重定向拖拽事件例如覆蓋在 iframe 上方的場景。FilePicker點擊打開文件選擇器client/components/file-picker/index.jsx 是一個輕量的點擊觸發(fā)組件其核心邏輯在 component-file-picker.js在頁面加載時預創(chuàng)建一個隱藏的form與input typefile見 L11-L16每次點擊調用input.click()彈出系統(tǒng)文件對話框并監(jiān)聽change事件把input.files通過onPick回傳支持multiple多選、directory選擇目錄、accept限定文件類型三個選項accept既支持字符串如application/zip也支持數(shù)組拼接。Upload Drop Zone 使用它時傳入acceptapplication/zip從而在系統(tǒng)文件對話框中直接過濾出 zip 文件。樣式表現(xiàn)與交互反饋style.scss 定義了上傳區(qū)域的視覺形態(tài)默認態(tài)position: relative的容器淺灰背景--color-neutral-0、2px 虛線邊框--color-neutral-light內容區(qū)固定 180px 高度、垂直水平居中懸停態(tài)邊框加深、整體上移 1px 并帶輕微陰影云朵上傳圖標cloud-upload48px同步變色給用戶“可交互”的反饋禁用態(tài)如上所述透明度降到 0.2 且阻斷事件。真實業(yè)務集成案例主題上傳頁Upload Drop Zone 在 wp-calypso 中的典型消費者是主題上傳頁面 client/my-sites/themes/theme-upload/index.jsx其接入方式可作為業(yè)務方的最佳實踐模板按需加載通過AsyncLoad配合 webpack 動態(tài)importwebpackChunkName: async-load-calypso-blocks-upload-drop-zone延遲加載組件避免拖慢首屏見 L79-L82差異化上傳策略doUpload根據(jù)站點類型分發(fā)——Jetpack 站點調用uploadTheme( siteId, file )非 Jetpack 站點調用initiateThemeTransfer( siteId, file, , , theme_upload )見 L292-L295權限與狀態(tài)聯(lián)動disabled由canUploadThemesOrPlugins站點是否具備FEATURE_UPLOAD_THEMES/FEATURE_UPLOAD_PLUGINS特性與自動化轉移資格共同決定上傳期間切換為進度條組件ThemeUploadProgress上傳完成后展示主題信息卡片。這一集成方式清晰展示了doUpload回調與disabled屬性的實際使用語境業(yè)務方負責一切與站點、權限、上傳協(xié)議相關的邏輯Upload Drop Zone 只專注于“收集一個合法的 zip 文件并交給回調”。小結Upload Drop Zone 是 wp-calypso 中一個職責劃分清晰的復合組件它通過組合DropZone與FilePicker把“拖拽”與“點選”兩種上傳入口收斂為統(tǒng)一的doUpload( siteId, file )回調并在內部完成單文件、類型與 50MB 大小限制的校驗。無論是參考 README 快速接入還是閱讀 index.jsx 理解校驗鏈路抑或參照 主題上傳頁 做權限、狀態(tài)與上傳協(xié)議的完整集成你都可以在本文的基礎上直接進入實戰(zhàn)?!久赓M下載鏈接】wp-calypsoThe JavaScript and API powered WordPress.com項目地址: https://gitcode.com/gh_mirrors/wp/wp-calypso創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考