# 一、FormData 对象

# 1、基本概述

  FormData 是一个内置的 JavaScript 对象,用于创建表单数据,并以键值对 key/value 的形式进行数据的管理。它通常用于将表单数据通过 AJAX 请求发送到服务器。

  在使用 FormData 对象时,不需要显式设置请求头的 Content-Type 为 multipart/form-data。这是因为在发送包含 FormData 对象的 AJAX 请求时,浏览器会自动设置适当的请求头

FormData 接口 (opens new window)

# 2、数据收集

// 1、使用方式1
var formElement = document.getElementById('myForm')
var formData = new FormData(formElement)

///2、使用方式2
var formData = new FormData()
// 单个
formData.append('username', 'John')
formData.append('email', '[email protected]')
// 批量
// Object.keys(this.pubForm).forEach((key) => {
//   fd.append(key, this.pubForm[key])
// })

// ================

var xhr = new XMLHttpRequest()
xhr.open('POST', 'https://api.example.com/submit')

xhr.send(formData)

# 3、应用场景

  常规情况下,我们上传的是application/json格式的数据。但在文件上传等特殊业务中,如果我们选择了 JSON 字符串传递参数,在使用 JSON.stringify()格式化参数数据时,会将 FileBlob 对象转化成{},文件数据会丢失。这个时候,我们就得上传multipart/form-data格式的数据。

# 二、draggable 拖放

  在正式的项目开发中,我们可以借助Vue-Draggable (opens new window)简化开发。

参考: draggable (opens new window)拖拽操作 (opens new window)

# 1、draggable 属性

  如果 draggable 属性没有设值,则默认值 为 auto,表示使用浏览器定义的默认行为。

也就是说:只有选择的文本、图像和链接可以被拖动

使用示例
<div class="container">
  <div class="top">
    <!--  加上draggable属性,使得item可拖拽 -->
    <div draggable="true" class="color1 item">color1</div>
    <div draggable="true" class="color2 item">color2</div>
    <div draggable="true" class="color3 item">color3</div>
  </div>
  <div class="content">
    <div class="box1">
      box1
      <div class="box2">
        box2
        <div class="box3"></div>
      </div>
    </div>
  </div>
</div>

# 2、拖放过程

  当元素或选中的文本在可释放目标上被释放时触发,想要 ondrop 能正确触发,有时需要在前置 ondragover 事件中禁用默认行为

  • 拖动事件:ondragstart
  • 放置事件:ondrop、ondragover

演示地址 (opens new window)

// 采用✨事件委托(监听所有拖拽事件)
const container = document.querySelector('.container')

// ==== 1、开始 =====

let dragElm
container.ondragstart = (e) => {
  console.log('你拖拽了:', e.target)

  dragElm = e.target
  e.dataTransfer.effectAllowed = 'move' // 拖动效果
}

// ==== 2、经过 =====

container.ondragover = (e) => {
  // 要想后面的drop事件生效,必须阻止浏览器的默认行为
  e.preventDefault()
  // console.log("被拖拽盒子经过", e.target); // 多次触发

  e.dataTransfer.dropEffect = 'move' // 放置效果
}

container.ondragenter = (e) => {
  console.log('被拖拽盒子经过', e.target) // 同种元素只触发一次
}

// ==== 3、结束 =====

container.ondrop = (e) => {
  console.log('最终放置位置为', e.target)

  dragElmClone = dragElm.cloneNode(true)
  e.target.appendChild(dragElmClone)
}

# 3、数据传递

  这里仅仅演示了 setDate()、getData() 方法,在后面的还会使用到它的 effectAllowed 属性、 files 属性等。

dataTransfer (opens new window)

function dragstart_handler(ev) {
  // 添加拖拽数据,key 可以为任意字符串
  ev.dataTransfer.setData('key', 'value')
  const data = ev.dataTransfer.getData('key')
}
回顾:自定义属性 H5
box2.dataset.effect = 'copy'
console.log(box2) // <div id="box2" data-effect="copy">采用H5挂载</div>

box2.dataset.effect
delete box.dataset.effect

# 三、FileReader 对象

  FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File (opens new window) 或 Blob 对象指定要读取的文件或数据。

FileReader 对象 (opens new window)

# 1、File 对象

  File 对象可以是来自用户在一个<input>元素上选择文件后返回的 FileList (opens new window) 对象,也可以来自拖放操作生成的 DataTransfer (opens new window) 对象,还可以是来自在一个 HTMLCanvasElement 上执行 mozGetAsFile()方法后返回结果

// 1、FileList
const fileList = document.querySelector('.file').files

// 2、DataTransfer
const fileList = event.dataTransfer.files
文件上传
<input id="fileSelect" type="file" />
<button class="upload">上传图片</button>
const uploadBtn = document.querySelector('.upload')

uploadBtn.onclick = function () {
  const fileList = document.querySelector('#fileSelect').files

  const formData = new FormData()
  formData.append('avatar', fileList[0])

  // ================

  var xhr = new XMLHttpRequest()
  xhr.open('POST', 'https://api.example.com/submit')

  xhr.send(formData)
}

# 2、FileList(input 元素)

演示地址 (opens new window)

<input id="fileSelect" type="file" />

<img class="imgPreview" src="" alt="图片预览" />
选择 + 图片预览
const fileSelect = document.querySelector('#fileSelect')
const previewElm = document.querySelector('.imgPreview')

fileSelect.onchange = function (event) {
  const fileList = event.target.files

  // ================
  // 1、使用base64字符串【data:image/jpeg;base64,/ 开头】

  const reader = new FileReader()
  reader.readAsDataURL(fileList[0])

  reader.onload = function (e) {
    // console.log(e.target); // FileReader对象
    previewElm.src = e.target.result
  }

  // ================
  // 2、使用内存临时地址【blob:http://localhost:8080/ 开头】

  previewElm.src = URL.createObjectURL(fileList[0])
  URL.revokeObjectURL(URL.createObjectURL(fileList[0])) // 释放资源
}
图片数据
const fileSelect = document.querySelector('#fileSelect')
const previewElm = document.querySelector('.imgPreview')

fileSelect.onchange = function (event) {
  const fileList = event.target.files

  // 数据1
  console.log(fileList[0]) // name、size、type、lastModifiedDate
  // ================

  const reader = new FileReader()
  reader.readAsDataURL(fileList[0])

  reader.onload = function (e) {
    var image = new Image()
    image.src = e.target.result

    image.onload = function () {
      // 数据2
      console.log('图片的宽度为' + this.width + ',长度为' + this.height)
    }
  }
}

# 3、DataTransfer(鼠标拖拽)

演示地址 (opens new window)

<div id="dropZone" style="width: 200px;height: 200px;background: skyblue;">放置区域</div>

<img class="imgPreview" src="" alt="图片预览" />
拖动 + 图片预览
const dropZone = document.querySelector('#dropZone')
const previewElm = document.querySelector('.imgPreview')

// 拖动流程
dropZone.ondragover = function (event) {
  event.preventDefault() // 防止不能drop
}

dropZone.ondrop = function (event) {
  const fileList = event.dataTransfer.files

  // ================

  if (fileList[0].type.match('image.*')) {
    previewElm.src = URL.createObjectURL(fileList[0])
    URL.revokeObjectURL(URL.createObjectURL(fileList[0]))
  }

  event.preventDefault() // 防止页面跳转
}
更新于 : 8/7/2024, 2:16:31 PM