Vue3 ベースのフルスクリーン ドラッグ アップロード コンポーネント

Vue3 ベースのフルスクリーン ドラッグ アップロード コンポーネント

この記事は主に、みんなで共有できるVue3ベースのフルスクリーンドラッグアップロードコンポーネントを紹介します。詳細は次のとおりです。

知識ポイント

  • ブラウザドラッグAPI
  • フェッチリクエスト
  • ヴュー3

長い話になりますが、簡単に言うと、HTML5 ドラッグ API を使用したドラッグ アンド ドロップ ソートの例をいくつか紹介しただけです。実際、考え方は他のドラッグ アンド ドロップ アップロード コンポーネントと基本的に同じで、ドラッグする領域を指定して、ファイルを読み込んでアップロードします。まずは、HTML5 の新しい API であるドラッグ API についてお話ししましょう。要素に draggable = true 属性を設定すると、その要素はドラッグをサポートします。ドラッグ要素のイベントは次のとおりです。

1. ondragは要素をドラッグするときにスクリプトを実行します
2. ondragstartはドラッグ操作の開始時にスクリプトを実行します。
3. ondragendはドラッグ操作が終了したときにスクリプトを実行します。

対象要素のイベントは次のとおりです。
1. ondragoverは、要素が有効なドロップターゲット上にドラッグされたときにスクリプトを実行します。
2. ondragenter 要素が有効なドラッグターゲットにドラッグされたときにスクリプトを実行します。
3. ondragleaveは、要素が有効なドラッグアンドドロップターゲットを離れたときに実行されるスクリプトです。
4. ondropはドラッグされた要素がドロップされるときにスクリプトを実行します。

たとえば、ボディの引きずりを監視したいとします。

const ele = document.querySelector('body')
ele.addEventListener('dragenter', (e) => {
  // 何かをする
})

デフォルトイベントを防止したい場合は、e.preventDefault() を使用します。

コンポーネント

まずは効果を見てみましょう。今回はpngとjpgのみアップロードするように設定しました

使用:

    <アップロード
      accept=".jpg,.png,.ico" // ファイルタイプを設定 @onChange="change" // ファイルアップロードイベント action="http://localhost:3001/upload" // アップロードアドレス: header="header" // アップロードされたヘッダー
      autoUpload // 自動的にアップロードするかどうか name="file" // アップロードされたフィールド名 @onSuccess="onSuccess" // アップロード成功コールバック></upload>

当初、ドラッグされた要素を取得したいときに、リスニング イベントを追加しても、ファイルをプレビューするために新しいウィンドウが開かれることがわかったので、最初のステップとして、すべてのデフォルト イベントを無効にしました。

// デフォルトのドラッグイベントを無効にする function enableDefaultEvents() {
  定数doc = document.documentElement
  doc.addEventListener('dragleave', (e) => e.preventDefault()) //ドラッグして離すdoc.addEventListener('drop', (e) => e.preventDefault()) //ドラッグしてドロップdoc.addEventListener('dragenter', (e) => e.preventDefault()) //ドラッグして入れるdoc.addEventListener('dragover', (e) => e.preventDefault()) //前後にドラッグ}

ドラッグのデフォルトイベントを防ぐためにルート要素を直接取得する

2 番目のステップは、監視するイベントを本体またはその他の要素に追加することです。ここで注意すべき点は、フルスクリーン ドラッグが実現できるように、本体の高さはウィンドウの高さと同じでなければならないということです。ドラッグするときに、ファイルが領域外にドラッグされているかどうかも判断する必要があります。

全体的な判決は次のとおりです。

e.target.nodeName === 'HTML'、これはルート要素がHTMLであるかどうかを判断するために使用されます
e.target === e.explicitOriginalTarget これは、2つのトリガーイベントのターゲットが一致しているかどうかを判定するFirefox固有のAPIです(!e.fromElement &&
        (e.clientX <= 0 ||
          e.clientY <= 0 ||
          e.clientX >= window.innerWidth ||
e.clientY >= window.innerHeight))

これは、マウスの現在の位置、つまりマウスがまだエリア内にあるかどうかを判断するために使用されます。

// ドラッグイベント関数を初期化する init() {
    // 本文要素を取得する const ele = document.querySelector('body')
  // イベントを追加 // ドラッグアンドドロップ ele.addEventListener('dragenter', () => {
    表示値 = true
  })
  // ここでマウスがドラッグされているかどうかを判断しますele.addEventListener('dragleave', (e) => {
    もし (
      e.target.nodeName === 'HTML' ||
      e.target === e.explicitOriginalTarget ||
      (!e.fromElement &&
        (e.clientX <= 0 ||
          e.clientY <= 0 ||
          e.clientX >= window.innerWidth ||
          e.clientY >= window.innerHeight))
    ){
      表示値 = false
    }
  })
  //ドラッグ inele.addEventListener('drop', (e) => {
    表示値 = false
    e.preventDefault()
    onDrop(e) // ファイルをドラッグして処理するメソッド})
}

3 番目のステップは、ドラッグされたファイルを処理することです。この時点で、 accept は定義したファイル タイプです。この時点で、ドラッグされたファイルを取得するために e.dataTransfer.files プロパティを使用できます。
次に、フィルターを使用してドラッグしたファイルをフィルタリングし、必要なファイルタイプのみを保持します。

checkType(file,accept) はファイルタイプを判定するために使用されます。この関数は、element ui のアップロードコンポーネントのフィルターに基づいています。私もこれを書いたときは混乱しました。

// ファイルタイプをチェックする function checkType(file, accept = '') {
  const { 型, 名前 } = ファイル
  (accept.length === 0) の場合は true を返す
  const extension = name.indexOf('.') > -1 ? `.${name.split('.').pop()}` : ''
  const baseType = type.replace(/\/.*$/, '')
  返品 承諾
    。スプリット('、')
    .map((type) => type.trim())
    .filter((type) => type)
    .some((受け入れられたタイプ) => {
      if (/\..+$/.test(acceptedType)) {
        戻り値の拡張子 === acceptedType
      }
      if (/\/\*$/.test(acceptedType)) {
        baseType === acceptedType.replace(/\/\*$/, '') を返します
      }
      (/^[^/]+\/[^/]+$/.test(acceptedType)) の場合 {
        戻り値の型 === acceptedType
      }
    })
}

このメソッドは、ファイルがドラッグされた後にそのファイルを処理するために使用されます。必要なファイルを取得したら、autoUpload を使用してアップロードするかどうかを決定します。

関数onDrop(e) {
  定数 accept = props.accept
  const list = [].slice.call(e.dataTransfer.files).filter((ファイル) => {
    (受け入れる)場合{
      checkType(file, accept) を返します
    }
    真を返す
  })
  ファイルリスト = list.map((p) => {
    handleStart(p) を返す
  })
  // イベント onChange() をトリガーする
  props.autoUploadの場合{
    props.action === ''の場合{
      エラー発生時()
      「行動が必要」を投げる
      戻る
    }
    list.forEach((ファイル) => {
      post(file) // ファイルをアップロードする })
  }
}

ソースコードは次のとおりです。

<テンプレート>
  <div class="mask" v-show="show" id="mask">
    <h3>アップロードするにはここにドラッグしてください</h3>
  </div>
</テンプレート>
<スクリプトの設定>
'vue' から { ref, reactive, onMounted } をインポートします。
// './ajax' から ajax をインポートします
const props = defineProps({
  name: String, // アップロードされたフィールド名 header: { Object, Number, String }, // アップロードされたファイルのヘッダー // 検証するファイルタイプ、値がある場合、すべてのファイルのみがドラッグされ、フィルター設定後のファイルのみが保持されます accept: {
    タイプ: 文字列、
    デフォルト: ''、
  },
  // 自動アップロードを有効にするかどうか autoUpload: {
    タイプ: ブール値、
    デフォルト: false、
  },
  // アドレスのアップロードアクション: {
    タイプ: 文字列、
    デフォルト: '#'、
  },
})

const emitting = defineEmits(['onError', 'onProgress', 'onSuccess', 'onChange']) // デフォルトのemitイベント let show = ref(false) // マスクを表示するかどうか let fileList = reactive([]) // ファイルリスト let tempIndex = 0 // マークを付ける onMounted(() => {
  デフォルトイベントを無効にする()
  初期化()
})
// ドラッグイベント関数を初期化する init() {
  const ele = document.querySelector('body')
  ele.addEventListener('dragenter', () => {
    表示値 = true
  }) //ドラッグアンドドロップele.addEventListener('dragleave', (e) => {
    もし (
      e.target.nodeName === 'HTML' ||
      e.target === e.explicitOriginalTarget ||
      (!e.fromElement &&
        (e.clientX <= 0 ||
          e.clientY <= 0 ||
          e.clientX >= window.innerWidth ||
          e.clientY >= window.innerHeight))
    ){
      表示値 = false
    }
  }) //ドラッグして離れるele.addEventListener('drop', (e) => {
    表示値 = false
    e.preventDefault()
    ドロップ時
  }) // ドラッグイン }
// デフォルトのドラッグイベントを無効にする function enableDefaultEvents() {
  定数doc = document.documentElement
  doc.addEventListener('dragleave', (e) => e.preventDefault()) //ドラッグして離すdoc.addEventListener('drop', (e) => e.preventDefault()) //ドラッグしてドロップdoc.addEventListener('dragenter', (e) => e.preventDefault()) //ドラッグして入れるdoc.addEventListener('dragover', (e) => e.preventDefault()) //前後にドラッグ}
//ドラッグインイベント関数onDrop(e) {
  定数 accept = props.accept
  const list = [].slice.call(e.dataTransfer.files).filter((ファイル) => {
    (受け入れる)場合{
      checkType(file, accept) を返します
    }
    真を返す
  })
  ファイルリスト = list.map((p) => {
    handleStart(p) を返す
  })
  変更時()
  props.autoUploadの場合{
    props.action === ''の場合{
      エラー発生時()
      「行動が必要」を投げる
      戻る
    }
    list.forEach((ファイル) => {
      投稿(ファイル)
    })
  }
}
// ファイルタイプをチェックする function checkType(file, accept = '') {
  const { 型, 名前 } = ファイル
  (accept.length === 0) の場合は true を返す
  const extension = name.indexOf('.') > -1 ? `.${name.split('.').pop()}` : ''
  const baseType = type.replace(/\/.*$/, '')
  返品 承諾
    。スプリット('、')
    .map((type) => type.trim())
    .filter((type) => type)
    .some((受け入れられたタイプ) => {
      if (/\..+$/.test(acceptedType)) {
        拡張子を返す === acceptedType
      }
      if (/\/\*$/.test(acceptedType)) {
        baseType === acceptedType.replace(/\/\*$/, '') を返します
      }
      (/^[^/]+\/[^/]+$/.test(acceptedType)) の場合 {
        戻り値の型 === acceptedType
      }
    })
}
// ファイルリストの戻り値を処理する function handleStart(rawFile) {
  rawFile.uid = Date.now() + tempIndex++
  戻る {
    ステータス: '準備完了'、
    名前: rawFile.name、
    サイズ: rawFile.size、
    パーセンテージ: 0,
    uid: rawFile.uid、
    生: 生ファイル、
  }
}
//アップロードイベント関数 post(rawFile) {
  定数オプション = {
    ヘッダー: props.header、
    ファイル: rawFile、
    データ: props.data || ''、
    ファイル名: props.name || 'ファイル',
    アクション: props.action、
  }
  アップロード(オプション)
    .then((res) => {
      res.json()
    })
    .then((json) => {
      成功時(json、rawファイル)
    })
    .catch((エラー) => {
      エラーが発生した場合(エラー、rawFile)
    })
}
// ファイルアップロードメソッド function upload(option) {
  const アクション = オプション.アクション

  const フォームデータ = 新しいフォームデータ()

  if (オプション.データ) {
    Object.keys(option.data).forEach((key) => {
      formData.append(キー、オプション.data[キー])
    })
  }
  formData.append(オプション.ファイル名, オプション.ファイル, オプション.ファイル名)

  const ヘッダー = 新しいヘッダー()
  for (let 項目をヘッダーに) {
    headers.hasOwnProperty(item) && headers[item] !== null の場合 {
      ヘッダーを追加します(i, オプション.ヘッダー[i])
    }
  }
  戻り値: fetch(action, {
    モード: 'no-cors'、
    本文: フォームデータ、
    ヘッダー: ヘッダー、
    メソッド: 'post'、
  })
}

// ドラッグしてファイルリストイベントを取得します function onChange() {
  出力('onChange', ファイルリスト)
}
//アップロードイベント関数 onProgress(e, file) {
  出力('onProgress', e, ファイル, ファイルリスト)
}
// アップロード成功イベント関数 onSuccess(res, file) {
  出力('onProgress', res, ファイル, ファイルリスト)
}
// アップロード失敗イベント関数 onError() {
  出力('onError')
}
</スクリプト>
<スタイルスコープ>
。マスク {
  上: 0;
  下部: 0;
  右: 0;
  左: 0;
  位置: 固定;
  zインデックス: 9999;
  不透明度: 0.6;
  テキスト配置: 中央;
  背景: #000;
}
h3 {
  マージン: -0.5em 0 0;
  位置: 絶対;
  上位: 50%;
  左: 0;
  右: 0;
  -webkit-transform: translateY(-50%);
  -ms-transform: 変換Y(-50%);
  変換: translateY(-50%);
  フォントサイズ: 40px;
  色: #fff;
  パディング: 0;
}
</スタイル>

これで、Vue3 ベースのフルスクリーン ドラッグ アンド ドロップ アップロード コンポーネントに関するこの記事は終了です。Vue3 フルスクリーン ドラッグ アンド ドロップ アップロードに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue3.0はvue-grid-layoutプラグインを使用してドラッグレイアウトを実装します。

<<:  MySQL 最適化のケーススタディ

>>:  Nginxの仕組みの詳細な説明

推薦する

JSON.stringify のさまざまな用途のまとめ

序文json を使用したことがある人なら、オブジェクトを文字列化してからバックエンドに送信するのが一...

HTML2 キャンバス SVG が認識されない場合の解決策

ウェブページを画像としてキャプチャする新機能があったので、人気のhtml2canvasを使ってみまし...

見落としがちなMySQLのCOLLATIONの例の詳細な説明

序文MySQL データベースの文字列型は、CHAR、VARCHAR、BINARY、BLOB、TEXT...

Windows での MySQL インストール チュートリアル (画像とテキスト付き)

MySQL インストール手順 MySQL は、スウェーデンの MySQL AB によって開発された...

DIVマスクを使用して、マウスでチェックボックスを直接チェックすることが無効である問題を解決します

フロントエンドの開発過程で、チェックボックスが必要な状況が発生しました。ユーザー操作の利便性を考慮し...

Windows 環境での MySQL 8.0 のインストール、設定、アンインストール

ソフトウェアバージョンウィンドウズ: ウィンドウズ10 MySQL: mysql-8.0.17-wi...

ノード スキャフォールディングを使用してトークン検証を実装するサーバーを構築する方法

コンテンツスキャフォールディングを使用してノードプロジェクトを素早く構築するデータベースとやり取りす...

MySQL 8.0.11 Community Green Edition の Windows 用インストール手順図

このチュートリアルでは、インストールに最新の MySQL コミュニティ グリーン バージョンである ...

HTMLタグのtarget属性の使用法

1: <a> タグを使用してページにリンクする場合、target 属性の役割は誰もが知っ...

Dockerコンテナ内で2つのプロセスを開始するときのDockerfile実装コード

最近、cronスケジュールタスク用のdockerを作りたいと思っており、Dockerfileで次のよ...

Nginx 構成の実装 HTTPS セキュリティ認証

1. HttpとHttpsの違いHTTP: インターネットで最も広く使用されているネットワーク プロ...

ウェブサイトのパフォーマンス: 画像とCookieの最適化、モバイルアプリケーションの最適化

前のセクションでは、コンテンツ、サーバー、JavaScript、CSS など、Web サイトのパフォ...

docker 環境でのデータベース バックアップ (postgresql、mysql) のサンプル コード

目次posgresql バックアップ/リストアMySQL バックアップ/復元posgresql バッ...

Web デザインにおける HTML フォーマットと長いファイルに関するヒント

<br />関連記事: Web コンテンツ ページ作成に関する 9 つの実用的な提案、W...