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

推薦する

ウェブサイト製品設計の参考となるいくつかの原則

以下の分析は製品設計原則に関するものですが、そのほとんどはウェブサイト製品に基づいているため、ユーザ...

さまざまな種類のMySQLインデックス

インデックスとは何ですか?インデックスは、データベース ストレージ エンジンが指定されたデータをすば...

JavaScript でのカスタム スワイパー コンポーネントの詳細な説明

目次エフェクト表示コンポーネント設定ステップ1ステップ2ステップ3コンポーネントの使用ステップ1ステ...

Linux の who コマンド例の紹介

誰についてシステムにログインしているユーザーを表示します。 who コマンドを実行すると、現在システ...

openlayers6のマップオーバーレイの詳細な説明

1. オーバーレイの概要オーバーレイとは、その名の通り、別の形で地図上に表示される、覆うことを指しま...

MySQL で UTF-8 エンコーディングを使用しないのはなぜですか?

MySQL UTF-8 エンコーディングMySQL は 2003 年のバージョン 4.1 から U...

RedHat 6.5/CentOS 6.5 に MySQL 5.7.20 をインストールするための詳細なチュートリアル

rpmインストールパッケージをダウンロードするMySQL公式サイト: https://dev.mys...

ボタンをクリックして画像を切り替える JavaScript

この記事の例では、ボタンをクリックすることで画像を切り替えることを実現するJavaScriptの具体...

React+Ant Design開発環境をセットアップするための実装手順

基礎1. スキャフォールディングを使用してプロジェクトを作成し、開始する1.1 足場を設置する: n...

JavaScript と JQuery フレームワークの基本チュートリアル

目次1. JS オブジェクトDOM –1、機能–2、テスト3. jQuery –1. 概要–2、使用...

MySQLが基礎データ構造としてB+ツリーを使用する理由

MySQL の基盤となるデータ構造が B+ ツリーであることは誰もが知っていますが、ではなぜ赤黒ツリ...

js 学習ノート: class、super、extends キーワード

目次序文1. es6の前にオブジェクトを作成する2. es6 後のクラス宣言3. クラスの継承4. ...

CPU、マシンモデル、メモリなどの情報を表示するLinuxシステム

システムメンテナンス中は、いつでも CPU 使用率を確認し、対応する情報に基づいてシステムの状態を分...

MySQLリモート接続失敗の解決策

以前、MySQLがローカルでは接続できるのにリモートでは接続できないという問題に遭遇したことがありま...

MySQL のインデックス障害の一般的なシナリオと回避方法

序文これまでにも、一部の SQL ステートメントを不適切に使用すると MySQL インデックスが失敗...