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

推薦する

WeChatミニプログラムページとコンポーネント間の情報伝達と機能呼び出し

今回は、私自身の開発経験を踏まえて、以下の観点で関連内容を解説します。ページからコンポーネントにデー...

アイデアがWebプロジェクトを公開した後、Tomcatサーバーがプロジェクトとそのソリューションを見つけることができません

概要プロジェクトは正常に作成され、正常にデプロイされましたが、以下に示すように、Tomcat サーバ...

MySQL ステートメントロックの実装の分析

概要: 2 つの MySQL SQL ステートメント ロックの分析次のSQL文にどのようなロックが追...

Alibaba Cloud で静的ウェブサイトを素早く構築する方法

序文:ジュニアプログラマーとして、私は自分自身の個人ウェブサイトを構築し、それを他の人に見せることを...

ページリファクタリングスキル - コンテンツ

雑談はここまでにして、インターネット上で見つかる高性能な Yahoo ウェブサイトを構築するための数...

Alibaba Cloud Server への Web プロジェクトのデプロイについて (5 つの手順)

1.まずAlibaba Cloudのウェブサイトにログインしてアカウントを登録し、サーバータイプを...

MySQL ビュー管理ビューの例の詳細説明 [追加、削除、変更、クエリ操作]

この記事では、例を使用して MySQL ビューの管理ビュー操作について説明します。ご参考までに、詳細...

Linux netfilter/iptables の知識ポイントの詳細な説明

ネットフィルターNetfilter は、パケット フィルタリング、転送、およびアドレス変換 NAT ...

mysql8.0.11 winx64 のインストールと設定方法のグラフィック チュートリアル (win10)

mysql 8.0.11 winx64のインストールチュートリアルは以下のように記録され、みんなと...

HTML ページ ヘッダー コード例の詳細な説明

知識ポイント1: ヘッダー情報にWebページのベースURLを設定するベース URL の本質は、ハイパ...

Mysql のデッドロックの表示とデッドロックの除去の詳細な説明

序文しばらく前にMysqlのデッドロック問題に遭遇したので、解決しました。問題の説明: Mysql ...

MySQL/MariaDB でピボット テーブルを実装する方法のサンプル コード

前回の記事では、Oracle でピボット テーブルを実装するいくつかの方法を紹介しました。今日は、同...

CSS3アニメーションとHTML5の新機能の詳しい説明

1. CSS3アニメーション☺CSS3 アニメーションは、JavaScript を介して要素のスタイ...

優れたグラフィックデザイナーが習得すべき7つのスキル

1》ウェブデザインが得意であること2》Webページのデザイン方法を知る3》計画する4. SEOを理解...

MySQL ログイン警告問題の解決策

1. はじめにMySQL にログインすると、次のような警告が表示されることがよくあります。警告: コ...