# 一、FormData 对象
# 1、基本概述
FormData 是一个内置的 JavaScript 对象,用于创建表单数据,并以键值对 key/value 的形式进行数据的管理。它通常用于将表单数据通过 AJAX 请求发送到服务器。
在使用 FormData 对象时,不需要显式设置请求头的 Content-Type 为 multipart/form-data。这是因为在发送包含 FormData 对象的 AJAX 请求时,浏览器会自动设置适当的请求头
# 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()格式化参数数据时,会将 File
和 Blob
对象转化成{}
,文件数据会丢失。这个时候,我们就得上传multipart/form-data
格式的数据。
# 二、draggable 拖放
在正式的项目开发中,我们可以借助Vue-Draggable (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
// 采用✨事件委托(监听所有拖拽事件)
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 属性等。
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 对象指定要读取的文件或数据。
# 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 元素)
<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(鼠标拖拽)
<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() // 防止页面跳转
}