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の仕組みの詳細な説明

推薦する

Portainer を使用して複数の Docker コンテナ環境を管理する方法を説明します。

目次Portainerは複数のDockerコンテナ環境を管理します2. Dockerを管理する2.1...

Docker に ElasticSearch をインストールする方法を 1 つの記事で解説

目次序文1. Dockerをインストールする2. ElasticSearchをインストールする3. ...

nginx の 2 つのモジュールの proxy_pass の違い

1. 1.ngx_stream_proxy_moduleモジュールのproxy_passディレクティ...

Windows10 mysql 8.0.12 非インストール版 設定 起動方法

この記事では、MySQL 8.0.12のインストールされていないバージョンを設定して起動するための具...

WeChatアプレットコンポーネント開発:視覚的な映画座席選択機能

目次1. はじめに1. コンポーネントデータ2. コンポーネントページのレイアウト1. ロゴエリアの...

データベースSQL SELECTクエリの仕組み

私たちは Web 開発者として、プロの DBA ではありませんが、データベースなしではやっていけませ...

Linuxカーネルスケジューラソースコード初期化の分析

目次1. はじめに2. スケジューラの基本概念2.1. 実行キュー (rq) 2.2 スケジューリン...

React tsx はランダムな検証コードを生成します

React tsxは参照用にランダムな検証コードを生成します。具体的な内容は次のとおりです。最近、t...

MySQL 8.0.15 のインストールと設定方法のグラフィックチュートリアル

この記事ではMySQL 8.0.15のインストールと設定方法を参考までに記録します。具体的な内容は以...

HTMLデータ送信投稿_PowerNode Java Academy

HTTP/1.1 プロトコルで指定されている HTTP リクエスト メソッドには、OPTIONS、...

一般的な XHTML タグの使用方法の紹介

XHTML には多くのタグがありますが、頻繁に使用されるのはごくわずかであり、習得する必要があるのは...

フロントエンドのパフォーマンス最適化 - フロントエンドエンジニアが話し合うべき問題点

はじめに<br />前回の記事「私の CSS アーキテクチャ コンセプト」では、公園で友...

アーティストの自己啓発におけるいくつかの経験

会社の影響力が拡大し、製品が改良され続けるにつれて、関連するイメージデザインもそれに追いつき、徐々に...

Vue3+Vite+TS は、要素プラスビジネスコンポーネントの二次カプセル化を実装します sfasga

目次1. 構造文字列2. タプルを返す3. Dict辞書にアクセスする4. 図書館を利用する5. リ...

JSは賞金の重さに基づいて当選確率を計算します

目次1. シナリオ例1.1. 抽選の賞品名を設定する1.2. 各賞の重みを設定する1.3. ラッキー...