一般的なアップロードコンポーネントの開発アップロード コンポーネントを開発する前に、次の点を理解する必要があります。
まず、基本的なアップロード プロセスを実装します。 基本的なアップロードプロセス。ボタンをクリックして選択し、アップロードを完了します。 コードは次のとおりです。 <テンプレート> <div class="アプリコンテナ"> <!--変更イベントを使用する--> <input type="file" @change="handleFileChange"> </div> </テンプレート> <script lang="ts"> 'vue' から {defineComponent} をインポートします。 'axios' から axios をインポートします エクスポートデフォルトdefineComponent({ 名前: 'アプリ'、 設定() { const handleFileChange = (e: イベント) => { // HTMLInputElementであることを確認します const target = e.target を HTMLInputElement として const ファイル = ターゲット.ファイル if(ファイル) { const アップロードされたファイル = ファイル[0] const フォームデータ = 新しいフォームデータ() formData.append('ファイル', アップロードされたファイル) //ノードを使用してアップロードインターフェースをシミュレートします。axios.post('http://localhost:3001/upload', formData, { ヘッダー: { 「コンテンツタイプ」: 'multipart/form-data' } })。その後(応答=> { コンソールログ('resp', resp) }).catch(エラー=> { }) } } 戻る { ファイル変更処理 } } }) </スクリプト> <スタイル> .ページタイトル{ 色: #fff; } </スタイル> 結果は次のとおりです。 この時点で、基本的なアップロードは処理されましたが、これは比較的簡単です。次に、Uploader.vue ファイルを作成して、Upload コンポーネントをカプセル化します。 以下の機能を実装する必要がありますカスタムテンプレートシステム独自のスタイルの <input type="file"> を使用すると見苦しいことがわかっているので、次のように対処する必要があります。
コードは次のとおりです。 <テンプレート> <div class="ファイルのアップロード"> <div class="アップロードエリア" @click="アップロードのトリガー"></div> <span v-if="fileStatus==='loading'">アップロード中</span> <span v-else-if="fileStatus==='success'">アップロードに成功しました</span> <span v-else-if="fileStatus==='error'">アップロードに失敗しました</span> <span v-else>クリックしてアップロード</span> <input ref="fileInput" type="file" name="file" style="display: none" /> </div> </テンプレート> <script lang="ts"> 'vue' から { computed, defineComponent, PropType, reactive, ref } をインポートします。 'axios' から axios をインポートします タイプ UploadStatus = '準備完了' | '読み込み中' | '成功' | 'エラー' エクスポートデフォルトdefineComponent({ 小道具: { action: { // URL アドレスタイプ: 文字列、 必須: true } }, セットアップ(プロパティ) { // ref="fileInput" に関連付けて取得された入力インスタンス オブジェクト const fileInput = ref<null | HTMLInputElement>(null) const fileStatus = ref<UploadStatus>('ready') // 1.div クリックイベント const triggerUpload = () => { if(ファイル入力値) { ファイル入力値クリック() } } // div を通じて入力変更イベントをトリガーします const handleFileChange = (e: Event) => { const target = e.target を HTMLInputElement として const ファイル = ターゲット.ファイル if(ファイル) { const アップロードされたファイル = ファイル[0] const フォームデータ = 新しいフォームデータ() formData.append('ファイル', アップロードされたファイル) readyFile.status = 'loading' // アップロードする前にステータスを「loading」に設定する axios.post(props.actions, フォームデータ, { ヘッダー: { 「コンテンツタイプ」: 'multipart/form-data' } })。その後(応答=> { コンソールログ('resp', resp) readyFile.status = 'success' // アップロードに成功し、ステータスを成功に設定します }).catch(エラー=> { readyFile.status = 'error' // // アップロードに失敗し、ステータスがエラーに設定されます }) } } 戻る { ファイル入力、 トリガーアップロード、 ファイル変更処理、 ファイルステータス } } }) </スクリプト> アップロード コンポーネント スタイルの最適化とアップロード ステータスの処理が完了したので、ファイル アップロード リストを処理する必要があります。 サポートファイルアップロードリストファイルアップロードリストを処理するには、次の実装が必要です。
前のコードに基づいていくつか変更を加えます。 <テンプレート> <div class="ファイルのアップロード"> <div class="アップロードエリア" @click="アップロードのトリガー"></div> <!-- クリックしてアップロード --> <スロット v-if="isUploading" name='ロード中'> <ボタンが無効>アップロード中</ボタン> </スロット> <!-- アップロードが完了しました --> <スロット名="アップロード済み" v-else-if="lastFileData && lastFileData.loaded" :uploadData="lastFileData.data"> <ボタンが無効>クリックしてアップロード</ボタン> </スロット> <!-- デフォルト状態 --> <スロット v-else name='default'> <!-- <button disabled>クリックしてアップロード</button> --> <span>クリックしてアップロード</span> </スロット> <input ref="fileInput" type="file" name="file" style="display: none" /> <!--ファイルリストを表示--> <ul> <li v-for="filesList 内のファイル" :key="ファイル.uid" :class="`アップロードされたファイルアップロード-${file.status}`" > <span class="filname"> {{ ファイル名 }} </span> <button class="delete-icon" @click="reomveFile(file.uid)">削除</button> </li> </ul> </div> </テンプレート> <script lang="ts"> 'lodash-es' から { last } をインポートします 'uuid' から { v4 を uuidv4 としてインポートします。 // アップロードステータスの種類を定義します UploadStatus = 'ready' | 'loading' | 'success' | 'error' // ステップ1 アップロードファイルオブジェクトインターフェイスクラスを定義するエクスポートインターフェイスUploadFile { uid: string; // ファイルの一意のID size: number; // ファイル サイズname: string; // ファイル名status: UploadStatus; // アップロード ステータスraw: File; // fileprogress?: string; // ファイルのアップロードの進行状況resp?: any; // サーバーが返すデータurl?: string // 対応する表示 URL } エクスポートデフォルトdefineComponent({ 小道具: { action: { // URL アドレスタイプ: 文字列、 必須: true } }, セットアップ(プロパティ) { // ref="fileInput" に関連付けて取得された入力インスタンス オブジェクト const fileInput = ref<null | HTMLInputElement>(null) // ステップ2 アップロードファイルリスト const filesList = ref<UploadFile[]>([]) // ステップ4-1 アップロードが進行中かどうかを判断する const isUploading = computed(()=> { filesList.value.some((file)=>file.status==='loading') を返します }) //step4-2 アップロードされたファイルの最後の項目を取得する const lastFileData = computed(()=>{ const lastFile = last(filesList.value) if(!lastFile) が false を返す 戻る { ロードされました: lastFile?.status === '成功'、 データ:lastFile?.resp } }) // 1.div クリックイベント const triggerUpload = () => { if(ファイル入力値) { ファイル入力値クリック() } } // div を通じて入力変更イベントをトリガーします const handleFileChange = (e: Event) => { const target = e.target を HTMLInputElement として const ファイル = ターゲット.ファイル if(ファイル) { const アップロードされたファイル = ファイル[0] const フォームデータ = 新しいフォームデータ() formData.append('file', アップロードされたファイル) // ステップ3 レスポンシブオブジェクトを設定し、ページに表示するために filesList に保存します。const fileObj = reactive<UploadFile>({ uid: uuid(); // ファイルの一意のID サイズ: uploadedFile.size、 名前: uploadedFile.name、 ステータス: '読み込み中'、 生: アップロードされたファイル }) ファイルリスト.値.push(fileObj) axios.post(props.actions, フォームデータ, { ヘッダー: { 「コンテンツタイプ」: 'multipart/form-data' }, //ステップ6 アップロードの進行状況を処理する onUploadProgress: (progressEvent)=> { 定数完了 = (progressEvent.loaded / progressEvent.total * 100 | 0) + '%' fileObj.progress = 完了 } })。その後(応答=> { コンソールログ('resp', resp) fileObj.status = '成功' }).catch(エラー=> { fileObj.status = 'エラー' }).finally(()=> { // 写真が再度アップロードされなくなるバグ if(ファイル入力値) { ファイル入力値.値 = '' } }) } } // ステップ7 プロセスの削除 const reomveFile = (uid: string) => { filesList.value = filesList.value.filter(ファイル=>ファイル.uid!==uid) } 戻る { ファイル入力、 トリガーアップロード、 ファイル変更処理、 ファイルステータス、 アップロード中です、 ファイルリスト、 最終ファイルデータ } } }) </スクリプト>
注意: 同じ画像を選択した場合、アップロードは実行されません。入力変更イベントを使用しているため、アップロード後に入力値を null に設定する必要があります。 一連のライフサイクルフックイベント、アップロードイベントをサポートアップロード前 <テンプレート> ... </テンプレート> <script lang="ts"> 'lodash-es' から { last } をインポートします 'uuid' から { v4 を uuidv4 としてインポートします。 // アップロードステータスの種類を定義します UploadStatus = 'ready' | 'loading' | 'success' | 'error' // アップロードされたファイルをブール値またはプロミスとして定義し、ファイルを受け入れる type CheckUpload = ()=> ブール値 | Promise<File> エクスポートインターフェースUploadFile { ... } エクスポートデフォルトdefineComponent({ 小道具: { action: { // URL アドレスタイプ: 文字列、 必須: true }, アップロード前: { タイプ: PropType<CheckUpload> としての関数 } }, セットアップ(プロパティ) { const fileInput = ref<null | HTMLInputElement>(null) const filesList = ref<UploadFile[]>([]) // ステップ4-1 アップロードが進行中かどうかを判断する const isUploading = computed(()=> { filesList.value.some((file)=>file.status==='loading') を返します }) const lastFileData = 計算された(()=>{ const lastFile = last(filesList.value) if(!lastFile) が false を返す 戻る { ロードされました: lastFile?.status === '成功'、 データ:lastFile?.resp } }) const トリガーアップロード = () => { if(ファイル入力値) { ファイル入力値クリック() } } const handleFileChange = (e: イベント) => { const target = e.target を HTMLInputElement として const ファイル = ターゲット.ファイル const アップロードされたファイル = ファイル[0] アップロード前にprops.beforeUpload()を実行すると、 const 結果 = props.beforeUpload(アップロードされたファイル) if (結果 && 結果インスタンスPromise) { 結果.then((processFile)=> { if (uploadedFile インスタンス of File) { postFile(アップロードされたファイル) } }).catch(エラー=>{ コンソール.エラー(エラー) }) } esle if(result===true) { postFile(アップロードされたファイル) } }それ以外{ postFile(アップロードされたファイル) } } const reomveFile = (uid: 文字列) => { filesList.value = filesList.value.filter(ファイル=>ファイル.uid!==uid) } // ファイルのアップロード処理 const postFile = (readyFile:UploadFile)=> { const フォームデータ = 新しいフォームデータ() formData.append('ファイル', readyFile.raw) readyFile.status = '読み込み中' axios.post(props.action, フォームデータ, { ヘッダー: { 「コンテンツタイプ」: 'multipart/form-data' }, onUploadProgress: (progressEvent) => { 定数完了 = (progressEvent.loaded / progressEvent.total * 100 | 0) + '%' // console.log('アップロード' + 完了) readyFile.progress = 完了 } }, ).then(resp=> { コンソールログ('resp', resp) // fileStatus.value = '成功' readyFile.status = '成功' readyFile.resp = resp.data }).catch(エラー=> { // ファイルステータス値 = 'エラー' readyFile.status = 'エラー' }) .finally(()=> { // 写真が再度アップロードされなくなるバグ if(ファイル入力値) { ファイル入力値.値 = '' } }) } 戻る { ファイル入力、 トリガーアップロード、 ファイル変更処理、 ファイルステータス、 アップロード中です、 ファイルリスト、 最終ファイルデータ } } }) </スクリプト> 実装手順:
onProgress、onSuccess、onError、onChangeは似ています ドラッグアンドドロップのサポート一般的なプロセスは次のとおりです。
v-onの使い方はvueの公式ドキュメントに記載されています。 上記のコード: <テンプレート> <div class="ファイルのアップロード"> <div :class="['upload-area', drag && isDragOver ? 'is-dragover': '' ]" v-on="イベント" > <!-- クリックしてアップロード --> <スロット v-if="isUploading" name='ロード中'> <ボタンが無効>アップロード中</ボタン> </スロット> <!-- アップロードが完了しました --> <スロット名="アップロード済み" v-else-if="lastFileData && lastFileData.loaded" :uploadData="lastFileData.data"> <ボタンが無効>クリックしてアップロード</ボタン> </スロット> <!-- デフォルト状態 --> <スロット v-else name='default'> <!-- <button disabled>クリックしてアップロード</button> --> <span>クリックしてアップロード</span> </スロット> </div> <input ref="fileInput" type="file" name="file" style="display: none" @change="handleFileChange" /> <ul> <li v-for="filesList 内のファイル" :key="ファイル.uid" :class="`アップロードされたファイルアップロード-${file.status}`" > <画像 v-if="file.url && listType === 'picture'" クラス="アップロードリストサムネイル" :src="ファイル.url" :alt="ファイル名" > <span class="filname"> {{ ファイル名 }} </span> <span class="進捗"> {{ファイル.進行状況}} </span> <button class="delete-icon" @click="reomveFile(file.uid)">削除</button> </li> </ul> </div> </テンプレート> <script lang="ts"> 'vue' から { computed, defineComponent, PropType, reactive, ref } をインポートします。 'axios' から axios をインポートします 'uuid' から { v4 を uuidv4 としてインポートします。 'lodash-es' から { last } をインポートします タイプ UploadStatus = '準備完了' | '読み込み中' | '成功' | 'エラー' タイプ fileListType = 'テキスト' | '画像' type CheckUpload = ()=> ブール値 | Promise<File> エクスポートインターフェースUploadFile { uid: string; // ファイルの一意のID size: 数値; // ファイル サイズname: 文字列; // ファイル名status: UploadStatus; // アップロード ステータスraw: File; // ファイルの進行状況?: 文字列; resp?: any; // サーバーから返されるデータ url?: string // 対応する表示 URL } // ファイルが領域にドラッグされると dragOver がトリガーされます // ファイルがドラッグ領域から出ると dragLeave がトリガーされます // drop イベントはドラッグされているファイルを取得し、クラスを削除してアップロードをトリガーします // ドラッグが設定されている場合にのみ機能します export default defineComponent({ 名前: 'アップローダー'、 小道具: { action: { // URL アドレスタイプ: 文字列、 必須: true }, beofreUpload:{ // アップロード前の処理 type: Function as PropType<CheckUpload> }, drag: { // ドラッグするかどうか type: Boolean, デフォルト: false }, autoUpload: { // 自動アップロードタイプ: ブール値、 デフォルト: true }, リストタイプ: { タイプ: PropType<fileListType> としての文字列、 デフォルト: 'テキスト' } }, セットアップ(プロパティ) { const fileInput = ref<null | HTMLInputElement>(null) const fileStatus = ref<UploadStatus>('ready') //アップロードされたファイルを保存する const filesList = ref<UploadFile[]>([]) // ドラッグされたスタイルを処理するための isDragOver フラグを定義します。アップロード領域の表示 const isDragOver = ref<boolean>(false) const トリガーアップロード = () => { if(ファイル入力値) { ファイル入力値クリック() } } イベント: {[キー:文字列]: (e: any)=>void} = { 'クリック': アップロードを開始、 } // ファイルが読み込み中状態にある限り、アップロード中であることを意味します const isUploading = computed(()=>{ filesList.value.some((file)=> file.status==='loading') を返します }) // アップロードされたファイルの最後の項目を取得します。const lastFileData = computed(()=>{ const lastFile = last(filesList.value) if(!lastFile) が false を返す 戻る { ロードされました: lastFile?.status === '成功'、 データ:lastFile?.resp } }) // dragover、dragleave を処理する const handleDrag = (e: DragEvent, over: boolean) => { // デフォルトイベントを防止します e.preventDefault() // dragover は true、dragleave は false isDragOver.value = オーバー } // ハンドルドロップ const handleDrop = (e: DragEvent) => { e.preventDefault() isDragOver.value = false if(e.dataTransfer) { アップロード前にチェック(e.dataTransfer.files) } } (props.drag)の場合{ イベント = { ...イベント、 'dragover': (e: DragEvent) => { handleDrag(e, true)}, 'dragleave': (e: DragEvent) => { handleDrag(e, false)}, 'ドロップ': ハンドルドロップ } // コンソール.log(イベント) } // ファイルを削除する const reomveFile = (uid: string)=> { filesList.value = filesList.value.filter(ファイル=>ファイル.uid!==uid) } const postFile = (readyFile:UploadFile) => { const フォームデータ = 新しいフォームデータ() formData.append('ファイル', readyFile.raw) readyFile.status = '読み込み中' // ファイルを選択したら、ストレージオブジェクトにプッシュします axios.post(props.action, formData, { ヘッダー: { 「コンテンツタイプ」: 'multipart/form-data' }, onUploadProgress: (progressEvent) => { 定数完了 = (progressEvent.loaded / progressEvent.total * 100 | 0) + '%' // console.log('アップロード' + 完了) readyFile.progress = 完了 } }, ).then(resp=> { コンソールログ('resp', resp) // fileStatus.value = '成功' readyFile.status = '成功' readyFile.resp = resp.data }).catch(エラー=> { // ファイルステータス値 = 'エラー' readyFile.status = 'エラー' }) .finally(()=> { // 写真が再度アップロードされなくなるバグ if(ファイル入力値) { ファイル入力値.値 = '' } }) } const addFileToList = (アップロードされたファイル: ファイル) => { const fileObj = リアクティブ<アップロードファイル>({ uid: uuidv4(), サイズ: uploadedFile.size、 名前: uploadedFile.name、 ステータス: '準備完了'、 生: アップロードされたファイル }) // 画像フォーマットを処理して表示する if(props.listType==='picture') { // 試す { // fileObj.url = URL.createObjectURL(アップロードされたファイル) // }catch(エラー) { // console.error('アップロードファイルエラー', err) // } const fileReader = 新しい FileReader() fileReader.readAsDataURL(アップロードされたファイル) ファイルリーダー.addEventListener('load', ()=> { fileObj.url = fileReader.result を文字列として }) } ファイルリスト.値.push(fileObj) props.autoUpload の場合 postFile(ファイルオブジェクト) } } const アップロードファイル = ()=> { // filesList.value.filter(file => file.status === 'ready').forEach(readyFile => postFile(readyFile)) filesList.value.filter(ファイル => ファイル.status === 'ready').forEach(readyFile=> postFile(readyFile)) } const beforeUploadCheck = (ファイル: null | FileList ) => { if(ファイル) { fileStatus.value = '読み込み中' const アップロードされたファイル = ファイル[0] if(props.beofreUpload) { 定数結果 = props.beofreUpload() // 戻り値がある場合 if(result && result instanceof Promise) { 結果.then(処理されたファイル=> { if (processedFile インスタンス of File) { 処理済みファイルをリストに追加 } それ以外 { 新しいエラーをスローします('beforeUpload promise はファイル オブジェクトを返す必要があります') } }).catch(エラー=> { コンソール.log(エラー) }) } そうでない場合(結果 === true) { アップロードされたファイルをリストに追加します } } それ以外 { アップロードされたファイルをリストに追加します } } } const handleFileChange = (e: イベント) => { const target = e.target を HTMLInputElement として const ファイル = ターゲット.ファイル beforeUploadCheck(ファイル) } 戻る { ファイル入力、 トリガーアップロード、 ファイル変更処理、 アップロード中です、 ファイルリスト、 ファイルを削除、 最後のファイルデータ、 アップロードチェック前、 ドラッグオーバー、 イベント } } }) </スクリプト> 上記は、vue3 に基づく基本的なアップロード一般コンポーネントです。アップロード インターフェース コードも添付されています。 // モジュールをインポート const Koa = require('koa'); 定数 fs = require('fs'); 定数パス = require('path'); const ルーター = require('koa-router')(); koaBody を require('koa-body'); const static = require('koa-static'); 定数 cors = require('koa2-cors') // インスタンス化 const app = new Koa(); app.use(koaBody({ multipart: true, // ファイルのアップロードをサポート formidable: { maxFieldsSize: 2 * 1024 * 1024, // 最大ファイルサイズは 2 MB multipart: true // マルチパート形式をサポートするかどうか} })); const uploadUrl = "http://localhost:3001/static/upload"; // ルーティングを設定する router.get('/', (ctx) => { // ヘッダー タイプを設定します。設定されていない場合は、ページが直接ダウンロードされます ctx.type = 'html'; // ファイルを読み取る const pathUrl = path.join(__dirname, '/static/upload.html'); ctx.body = fs.createReadStream(pathUrl); }); // ファイルをアップロード router.post('/upload', (ctx) => { // アップロードされたファイルを取得します。const file = ctx.request.files.file; console.log(ファイル); // ファイル ストリームを読み取る const fileReader = fs.createReadStream(file.path); // ファイルの保存パスを設定します。const filePath = path.join(__dirname, '/static/upload/'); // 絶対パスに組み立てます const fileResource = filePath + `/${file.name}`; /** * createWriteStream を使用してデータを書き込み、パイプ ストリーム スプライシングを使用します */ const writeStream = fs.createWriteStream(ファイルリソース); // /static/upload フォルダが存在するかどうかを確認し、存在しない場合は作成します if (!fs.existsSync(filePath)) { fs.mkdir(filePath, (err) => { もし(エラー){ 新しいエラー(err)をスローします。 } それ以外 { fileReader.pipe(書き込みストリーム); ctx.body = { url: uploadUrl + `/${file.name}`, コード: 0, メッセージ: 'アップロード成功 1' }; } }); } それ以外 { fileReader.pipe(書き込みストリーム); ctx.body = { url: uploadUrl + `/${file.name}`, コード: 0, メッセージ: 'アップロード成功 1' }; } }); //静的リソースパスを構成する app.use(static(path.join(__dirname))); // クロスドメインを有効にする app.use(cors()) // ルーティングを開始します app.use(router.routes()).use(router.allowedMethods()); // リスニングポート番号 app.listen(3001, () => { console.log('サーバーは3001でリッスンしています'); }); 最後に上記は単純な実装です。もちろん、カスタム ヘッダー、カスタム データ、アクセスなどを追加することもできます。 これで、Vue3 を使用してアップロード コンポーネントのサンプル コードを実装する方法についての記事は終了です。Vue3 アップロード コンポーネントに関するその他の関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Mac VMware Fusion CentOS7 静的 IP 構成チュートリアル図
>>: MySQL のメモリ使用量と CPU 使用率が高い場合のテストと解決策
スクリプトを書く目的は、さまざまなサービスを手動で起動しなくて済むようにすることです(怠惰のためでも...
目次最初の方法アプリ.vueホーム.vueホームコンテンツ.vueデータの応答性レスポンシブプロパテ...
MySQL は非常に強力なリレーショナル データベースです。しかし、初心者の中には、インストールや設...
よく使用されるコマンドは次のとおりです。 chmod 777 文件或目錄例: chmod 777 /...
実際の業務や面接では、「配列の重複排除」の問題によく遭遇します。以下は、js を使用して実装された配...
序文みなさんこんにちは。CSS ウィザードの alphardex です。以前、海外のウェブサイトを閲...
ユーティリティ = { /** * 死亡年ですか? * @return {Boolse} true...
Java で ffmpeg を呼び出してビデオ形式を flv に変換する方法の詳細な説明注:以下のプ...
MySQL では、char、varchar、text の各タイプのフィールドはすべて文字タイプのデー...
目次単一コンテンツ投影マルチコンテンツ投影単一条件のコンテンツ投影アプリ-人物-htmlアプリ担当者...
目次1. はじめに: 2. 最初のアイデアはインデックスを構築することです3. 命令P.S. Lik...
1. ウィンドウ -> 設定を選択してEclipseの設定パネルを開きます。 2. 「設定」ウ...
ビュー: MySQL のビューはテーブルと多くの類似点があります。ビューも複数のフィールドと複数のレ...
問題の説明VMware Workstationが新しい仮想マシンを作成し、64ビットオペレーティング...
長い間コンピューターで mysql を使用していなかったので、パスワードを忘れてしまいました。でも、...