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 設定チュートリアル

推薦する

Dockerでボリュームを管理する2つの方法

前回の記事では、Dockerの基礎知識であるローカルディレクトリのマウント方法を紹介しました。今日は...

少なくとも7日間連続して注文を行ったユーザーに対するSQLクエリ

テーブルを作成するテーブル order(id varchar(10),date datetime,o...

Hadoopカウンターとデータクリーニングの適用

データクリーニング (ETL)コアビジネスの MapReduce プログラムを実行する前に、まずデー...

JS における ES6 継承と ES5 継承の違い

目次継承ES5 プロトタイプ継承ES6 クラス継承両者の違いES5プロトタイプ継承の内部実装ES6 ...

MACでMYSQLデータベースのパスワードを忘れた場合の解決策

Mac オペレーティングシステムで MYSQL データベースのパスワードを忘れた場合の簡単な解決策1...

CentOS7.6 システムで yum を使用して lnmp 環境を構成する方法

1. インストールバージョンの詳細 サーバー: MariaDB サーバーバージョン: 5.5.60-...

MySQL の日付と時刻関数の概要 (MySQL 5.X)

1. MySQLは現在の日付と時刻を取得する関数1.1 現在の日付 + 時刻 (日付 + 時刻) ...

TypeScript のユニオン型、交差型、型ガード

目次1. ユニオンタイプ2. クロスオーバータイプ3. 型保護3.1 カスタム型保護3.2 保護の種...

CSS3 は、跳ねるボール効果を実現する Web アニメーションを作成します。

基本的な準備この実装には、クラス名が ball である単純な div が必要です。 HTMLコード:...

ウェブサイトのパフォーマンスを向上させるためのウェブサーバーの改善

<br />このシリーズの最初のセクションでは、Web サイトのパフォーマンスを向上させ...

HTML の div、td、p およびその他のコンテナーでの強制改行と非改行の実装

1. 改行を強制せず、省略記号で終了します。コードをコピーコードは次のとおりです。 <div ...

DockerでGDBを使用するときにブレークポイントを入力できない問題を解決する

質問docker で gdb を実行すると、ブレークポイントに到達しますが、ブレークポイントに入るこ...

JavaScript のディープコピーの落とし穴

序文以前、ある会社の面接に行ったとき、面接官から「オブジェクトを深くコピーするにはどうすればよいです...

MySQL カーソル関数と使用法

目次意味カーソルの役割カーソルの使用カーソルの宣言カーソルを開くカーソルデータのトラバースカーソルを...

mysql はインデックスを無効にしますか?

mysql の IN はインデックスを無効にしますか?しませんよ! 結果をご覧ください: mysq...