Vueはドラッグアンドドロップまたはクリックで写真をアップロードする機能を実装しています

Vueはドラッグアンドドロップまたはクリックで写真をアップロードする機能を実装しています

この記事では、ドラッグアンドドロップやクリックによる画像のアップロードを実現するためのVueの具体的なコードを参考までに紹介します。具体的な内容は次のとおりです。

1. プレビュー画像

2. 実装

クリックしてアイデアをアップロードします。ファイルをアップロードするには、入力タイプを「ファイル」に設定します。入力ボックスを非表示にし、ボタンがクリックされたときに入力のクリックアップロード機能を呼び出します。残っているのは CSS を使用してページを最適化することだけです。

ドラッグ アンド ドロップ アップロードの考え方は、ドラッグ イベントをドロップボックスにバインドし、コンポーネントが破棄されたときにイベントをアンバインドすることです。ドラッグが終了したら、event.dataTransfer.files を通じてアップロードされたファイルの情報を取得します。次に、ファイルをサーバーにアップロードします。

次に、各コンポーネントについて簡単に紹介します。

upload.vue はクリックしてアップロードするロジックをカプセル化していますが、プログレスバーは作成されていません。プログレスバーは、パーセントをパラメータとして後で改善できます。uploadFormDialog.vue は親ボックス、つまりアップロードボタンをクリックした後に表示されるダイアログボックスです。このコンポーネントでは、ページのレイアウト、ドラッグアンドドロップアップロードなどのロジックを完成させる必要があります。

このカプセル化の目的は、コードの保守を容易にすることです。

upload.vue クリックしてコンポーネントをアップロードします

<テンプレート>
    <!--upload.vue クリックしてコンポーネントをアップロードします-->
    <div class="ファイルセレクタ">
        <z-btn class="セレクターbtn" color="プライマリ" @click="ハンドルアップクリック">
            ファイルを選択</z-btn>
        <入力
            ref="入力"
            class="ファイルセレクタ入力"
            タイプ="ファイル"
            :multiple="複数"
            :accept="受け入れる"
            @change="handleFiles"
        />
    </div>
</テンプレート>
<スクリプト>
    'lodash/function' から {debounce} をインポートします。
    エクスポートデフォルト{
        データ() {
            戻る {
                受け入れる: '.jpg、.jpeg、.png、.gif'、
                複数: 偽、
                list: [], // 選択されたファイルオブジェクト uploadFinished: true, // アップロードステータス startIndex: 0, // アップロード開始インデックス(ファイルの追加に使用) maxSize: 10 * 1024 * 1024, // 10M(バイト単位のサイズ)
                // ソース: this.$axios.CancelToken.source(), // axios はリクエストをキャンセルします};
        },
        メソッド: {
            // リセット reset() {
                このリスト = [];
                this.source.cancel();
                this.startIndex = 0;
                this.uploadFinished = true;
                this.$refs.input && (this.$refs.input.value = null);
            },
            // アップロード関数を呼び出す handleUpClick: debounce(function () {
                // ここでアップロードステータスを維持し、アップロード処理中はアップロードボタンを無効にすることができます // if (!this.uploadFinished) this.$message.info('前のファイルは上書きされます~');
                this.$refs.input.click();
            }, 300),
            ハンドルファイル(e) {
                const ファイル = e?.target?.files;
                this.readFiles(ファイル);
            },
            // アップロードする前にファイルをオブジェクトに処理する readFiles(files) {
                if (!files || files.length <= 0) {
                    戻る;
                }
                for (const ファイル) {
                    定数 url = window.URL.createObjectURL(ファイル);
                    定数オブジェクト = {
                        title: file.name.replace(/(.*\/)*([^.]+).*/ig, '$2'), // ファイルサフィックス url を削除します。
                        ファイル、
                        ファイルタイプ: ファイルタイプ、
                        status: 0, // ステータス -> 0 待機中、1 完了、2 アップロード中、3 アップロード失敗 percent: 0, // アップロードの進行状況};
                    // アップロードするファイルを保存するために、事前にデータ内にリストを定義します。this.list.unshift(obj);
                    this.$emit('fileList', this.list);
                }
                // 最初はデータの startIndex を 0 に定義し、アップロードが完了したらアップロードされたファイルを追加するために更新します // this.startUpload(this.startIndex);
            },

        }
    };
</スクリプト>
<スタイル lang="scss">
.ファイルセレクター{
    .セレクターボタン{
        &:ホバー{
            背景色: rgba($color: #2976e6, $alpha: 0.8);
            遷移: 背景 180 ミリ秒;
        }
    }

    &-入力{
        表示: なし;
    }
}
</スタイル>

uploadFormDialog.vue アップロードダイアログボックス

<テンプレート>
    <!-- アップロードダイアログ -->
    <フォームダイアログ
        v-model="$attrs.value"
        :title="タイトル"
        持続的
        :loading="読み込み中"
        最大幅="600px"
        最小高さ='400px'
        @cancel="キャンセル処理"
        @confirm="handleSubmit"
    >
        <div
            クラス="d-flex flex-row justify-space-between">
            <z-form style='幅: 260px; 高さ: 100%;'>
                <form-item label="画像名" 必須>
                    <z-テキストフィールド
                        v-model="フォームデータ名"
                        概説
                        :rules="ルール"
                        :disabled='無効'
                        placeholder="画像の名前を入力してください"
                    >
                    </z-テキストフィールド>
                </フォーム項目>
                <form-item label="説明" 必須>
                    <z-テキストエリア
                        v-model="フォームデータの説明"
                        概説
                        :disabled='無効'
                        placeholder="説明を入力してください"
                        スタイル="resize: none;"
                    >
                    </z-テキストエリア>
                </フォーム項目>
            </z-フォーム>
            <div ref="pickerArea" class="rightBox">
                <div class="uploadInputs d-flex flex-column justify-center align-center" :class="[ ドラッグ ? 'ドラッグ' : '']">
                    <div ref="uploadBg" class="uploadBg my-2"></div>
                    <アップロード
                        ref="アップロードボタン"
                        @fileList='ファイルリスト'
                    </アップロード>
                    <div class="tip mt-2">アップロードボタンをクリックするか、ファイルをボックスにドラッグしてアップロードします</div>
                    <div class="tinyTip ">10M 以下のファイルを選択してください</div>
                </div>
            </div>
        </div>

    </フォームダイアログ>

</テンプレート>
<スクリプト>
    'lodash/function' から {debounce} をインポートします。
    './upload' からアップロードをインポートします。
    '@/wv-main-admin/apis/image' から {uploadImage} をインポートします。

    エクスポートデフォルト{
        コンポーネント:
            アップロード
        },
        プロパティ: ['dialogData'],
        データ() {
            戻る {
                ダイアログフラグ: ''、
                タイトル: 「画像の追加/編集」
                読み込み中: false、
                フォームデータ: {
                    名前: ''、
                    説明: ''
                },
                無効: false、
                ルール: [v => !!v || '必須'],
                データ: {}、
                dragging: true, //ドラッグするかどうかbindDrop: false,
                ファイル情報: {},
            };
        },

        マウント() {

        },
        破棄する前に() {
            // コンポーネントが破棄される前にドラッグイベントをアンバインドする try {
                const dropbox = this.$refs.pickerArea;
                dropbox.removeEventListener('drop', this.handleDrop);
                dropbox.removeEventListener('dragleave', this.handleDragLeave);
                dropbox.removeEventListener('dragover', this.handleDragOver);
                this.bindDrop = false;
            } catch (e) { console.log(e, '=======コンポーネントが破棄される前にドラッグ イベントをバインド解除する際に例外が発生します'); }
        },
        メソッド: {
            //キャンセル handleCancle() {
                // 現在のポップアップ ボックスを閉じます this.$emit('input', false);
                // コンポーネントを強制的に更新します。this.$forceUpdate();
            },
            handleSubmit: デバウンス(function() {
                // 1 つのファイルをアップロードします const flag = this.checkMustsItem();
                if (フラグ) {
                    アップロードを開始します。
                    //アップロードが完了したら、コンポーネントを強制的に更新します。$forceUpdate();
                }
            }, 300),

            //サブコンポーネントの値をリッスンする fileList(data) {
                this.fileInfo = データ[0];
                this.formData.name = this.fileInfo.title;
                定数 uploadBg = this.$refs.uploadBg;
                //背景画像を変更する uploadBg.style.backgroundImage = `url(${this.fileInfo.url})`;
            },
            バインドイベント() {
                const dropbox = this.$refs.pickerArea;
                // 重複したバインディングイベントを防ぐには、データ内でbindDropをfalseに初期化する必要があります。
                if (!dropbox || this.bindDrop) { return; }
                // ドラッグ イベントをバインドし、コンポーネントが破棄されたときにバインドを解除します。dropbox.addEventListener('drop', this.handleDrop, false);
                dropbox.addEventListener('dragleave', this.handleDragLeave);
                dropbox.addEventListener('dragover', this.handleDragOver);
                this.bindDrop = true;
            },
            // アップロードエリアにドラッグ handleDragOver(e) {
                e.stopPropagation();
                e.preventDefault();
                this.dragging = true;
            },
            // アップロードエリアを離れる handleDragLeave(e) {
                e.stopPropagation();
                e.preventDefault();
                this.dragging = false;
            },
            //ドラッグ終了 handleDrop(e) {
                e.stopPropagation();
                e.preventDefault();
                this.dragging = false;
                const ファイル = e.dataTransfer.files;
                // <upload/> コンポーネントのアップロード関数を呼び出します。 this.$refs.uploadBtn && this.$refs.uploadBtn.readFiles(files);
            },
            // アップロードする前にファイルを検証する必要があります checkFile(index) {
                const ファイル = this.list[インデックス];
                // ファイルが存在しない場合は、すべてのファイルがアップロードされます if (!file) {
                    //アップロードが完了したら、親コンポーネントに成功イベントをスローします。this.uploadFinished = true;
                    this.$emit('success', this.list);
                    // 変更イベントが正常にトリガーされるように、アップロード コントロールの値をクリアします。this.$refs.input.value = null; this.startIndex = index > 1 ? index - 1 : 0;
                    false を返します。
                }

                // アップロードされたかどうかを確認します if (`${file.status}` === '1') {
                    this.startUpload(++インデックス);
                    false を返します。
                }

                // ファイルサイズをチェックします if (this.maxSize && file.file && file.file.size >= this.maxSize) {
                    this.startUpload(++インデックス);
                    false を返します。
                }

                true を返します。
            },
            チェック必須項目() {
                if (!this.fileInfo.file) {
                    this.$message.warning('ファイルをアップロードしてください!');
                    false を返します。
                } if (!this.formData.name) {
                    this.$message.warning('ファイル名を入力してください!');
                    false を返します。
                } if (!this.formData.description) {
                    this.$message.warning('ファイルの説明を入力してください!');
                    false を返します。
                }
                true を返します。
            },
            // 単一のファイルをアップロードする startUpload() {
                this.loading = true;
                定数パラメータ = {
                    タイプ: '画像'
                };
                this.$set(params, 'file', this.fileInfo.file);
                this.$set(params, 'name', this.formData.name);
                this.$set(params, 'description', this.formData.description);
                アップロード画像(パラメータ)
                    .then(res => {
                        this.loading = false;
                        (res.code === 0)の場合{
                            this.$message.success('アップロードに成功しました~');
                            this.$emit('refreshList', false);
                            this.$emit('input', false);
                        }
                    })
                    .catch(() => {
                        this.loading = false;
                    });
                // this.$axios({
                // url: this.url, // アップロードインターフェース、props によって渡される // メソッド: 'post',
                // データ、
                // withCredentials: true、
                // cancelToken: this.source.token、 // インターフェースリクエストをキャンセルするために使用されます // // 進行状況バー // onUploadProgress: e => {
                // if (fileObj.status === 1) { return; } // アップロード済み // // 最大値は 99% に制限されます
                // 定数 p = parseInt((e.loaded / e.total) * 99);
                // if (e.total) {
                // fileObj.status = 2; // アップロード中 // fileObj.percent = p; // アップロードの進行状況を更新 // } else {
                // fileObj.status = 3; // アップロードに失敗しました // }
                // },
                // })
                // .then(レスポンス => {
                // if (`${response.code}` === '200') {
                // ファイルObj.ステータス = 1;
                // ファイルオブジェクトパーセント = 100;
                // } それ以外 {
                // ファイルObj.ステータス = 3;
                // }
                // })
                // .catch(e => {
                // console.log(e, '====エラー');
                // ファイルObj.ステータス = 3;
                // })
                // .finally(e => {
                // console.log(e, '====エラー');

                // this.startUpload(++index);
                // });
                // アップロードが完了しました},
        },
    };
</スクリプト>

<style lang='scss' スコープ>
    .rightBox{
        幅: 260ピクセル;
        高さ: 250px;
        境界線: 1px 実線 #ccc;
        上マージン: 18px;

        .uploadBg {
            幅: 150ピクセル;
            高さ: 125px;
            背景: url("../../../../assets/upload.png") 繰り返しなし 中央 中央;
            背景サイズ: 含む;
        }
        。ヒント {
            フォントサイズ: 13px;
            色: rgba(0, 0, 0, 0.87);
        }
        .tinyTip {
            フォントサイズ: 12px;
            色: #8e8f9e;
        }
    }

</スタイル>

注: 上記のコードは、当社独自のカプセル化されたコンポーネント ライブラリと、当社でカプセル化したいくつかのメソッドを使用しています。特定のシナリオに応じて、関連する変更を行ってください。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Vue vant-uiはvan-uploaderを使用してアバターアップロード機能を実装します
  • ユーザーがアップロードした写真の幅と高さを検出するVueメソッド
  • Vue+Element-UIは画像のアップロードと圧縮を実現します
  • Vue.js を使用して Alibaba Cloud OSS ストレージに画像をアップロードする方法の例
  • 写真をアップロードするための Vue axios フォーム送信例
  • Vue3.0 モバイル端末二次カプセル化 van-uploader による写真のアップロード (vant コンポーネント ライブラリ)

<<:  MySQLサービスを削除する具体的な方法

>>:  Nginx/Httpd ロードバランシング Tomcat 設定チュートリアル

推薦する

CentOS で LibreOffice を使用してドキュメント形式を変換する方法

プロジェクト要件では、アップロードされたドキュメントの前処理が必要です。ユーザーが doc 形式でド...

Docker-compose におけるdepends_on 順序問題を解決する方法についての簡単な説明

コンテナをソートするためにdepends_onを使用しても、コンテナ間の依存関係の問題は完全には解決...

Dockerコンテナの起動失敗を解決する方法

質問: コンピュータを再起動した後、docker の mysql コンテナを再起動できません。原因が...

Bootstrap 3.0 学習ノート グリッドシステム事例

序文前回の記事では、主にグリッドシステムの基本原理を学び、簡単なケースを通してその原理を実践しました...

ウェブページの幅を携帯電話の画面(ビューポート)の幅に自動的に適応させる実装コード

一般的な書き方は次のとおりです。 XML/HTML コードコンテンツをクリップボードにコピー<...

MySQL ALTERコマンドの知識ポイントのまとめ

テーブル名を変更したり、テーブル フィールドを変更したりする必要がある場合は、 MySQL ALTE...

MySQLはPartition関数を使用して水平分割戦略を実装します。

目次1件のレビュー2 水平分割の5つの戦略2.1 ハッシュ2.2 範囲2.3. キー2.4. リスト...

CSS で画像アダプティブ コンテナを実装するためのサンプル コード

多くの場合、画像をコンテナのサイズに合わせて調整する必要があります。 1. imgタグ方式幅と高さを...

JavaScript セレクター関数 querySelector および querySelectorAll

目次1. querySelectorは単一の要素を照会する1. ドキュメントインスタンスの呼び出し2...

Tomcat で server.xml と content.xml を変更した後の自動復元の問題の解決方法

設定ファイルを server.xml と content.xml に書き込みます。サーバーを再起動す...

MySQL 8.0.18 ハッシュ結合は左/右結合をサポートしていません 左と右の結合の問題

MySQL 8.0.18 では、インデックスが作成されていないフィールドに適用でき、等価値の関連付け...

Vue での props の使い方の紹介

序文: Vue では、props を使用して、もともと分離されていたコンポーネントを直列に接続するこ...

CentOS 7.x dockerはoverlay2ストレージ方式を使用する

/etc/docker/daemon.json を編集し、以下を追加します。 { "ストレ...

ショートカットアイコンとアイコンコードの違いの紹介

ステートメント 1: <link rel="shortcut icon" ...

Vue+canvas は、ウォーターフォール チャートを上から下までリアルタイムに更新する効果を実現します (QT と同様)

早速ですが、デモ画像をご紹介します。実装されている機能は、左側に凡例、右側にウォーターフォール チャ...