介绍
react-dropzone
是一个 HTML5 兼容的 React 组件,用于处理文件的拖放。
HTML5 支持使用<input type="file" />
. react-dropzone
为您提供附加功能,例如自定义放置区、显示预览以及限制文件类型和数量。
注意:如果您使用 Vue 而不是 React,请参阅我们的vue-dropzone
.
在本教程中,您将了解如何添加react-dropzone
到您的 React 项目并探索它提供的一些功能。
先决条件
要完成本教程,您需要:
- Node.js 的本地开发环境。遵循如何安装 Node.js 并创建本地开发环境。
本教程已通过 Node v15.3.0、npm
v7.4.0、react
v17.0.1 和react-dropzone
v11.2.4 验证。
步骤 1 — 设置项目
从使用create-react-app
生成 React App 开始,然后安装依赖项:
- npx create-react-app react-dropzone-example
切换到新的项目目录:
- cd react-dropzone-example
安装react-dropzone
:
- npm install react-dropzone@11.2.4
此时,您有一个带有react-dropzone
.
第 2 步 – 添加 Dropzone 组件
react-dropzone
具有默认设置,允许您以最少的配置添加它。
至少,您需要一个onDrop
属性来处理丢弃的文件和一些号召性用语,以帮助限制任何用户混淆:
import React, { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
function DropzoneComponent() {
const onDrop = useCallback(acceptedFiles => {
console.log(acceptedFiles);
}, []);
const {
getRootProps,
getInputProps
} = useDropzone({
onDrop
});
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
<div>Drag and drop your images here.</div>
</div>
)
}
export default DropzoneComponent;
此代码为您的应用程序提供拖放功能。
注意:值得注意的是,即使react-dropzone
被设计为拖放文件,默认情况下它也接受点击事件到放置区,这将启动文件选择对话框。
将组件添加到您的 React 应用程序:
import DropzoneComponent from './DropzoneComponent';
function App() {
return (
<div className="App">
<DropzoneComponent />
</div>
);
}
export default App;
运行您的应用程序并在 Web 浏览器中观察它。您应该会看到一个带有文本的 div: Drag and drop your images here
。
尝试将各种文件拖放到 React Dropzone 组件。该代码当前使用 aconsole.log
来显示文件。从上传的文件的信息包括name
,lastModified
,size
,和type
。
此时,您有一个使用默认配置的可工作的 React Dropzone 组件。该react-dropzone
文档附加的配置选项。
第 3 步 – 设置 Dropzone 组件的样式
默认情况下,react-dropzone
将没有样式。该文档提供了通用外观的样式,该外观使用 flexbox 和虚线边框的组合来向用户指示拖放文件的区域。
react-dropzone
还支持组件主动与 ( isDragActive
)交互、接受文件 ( isDragAccept
) 或拒绝文件 ( isDragReject
)时的道具。
当应用于 JPEG 和 PNG 图像文件类型时,重新访问DropzoneComponent
并修改它以使用isDragActive
、isDragAccept
和isDragReject
:
import React, { useCallback, useMemo } from 'react';
import { useDropzone } from 'react-dropzone';
const baseStyle = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '20px',
borderWidth: 2,
borderRadius: 2,
borderColor: '#eeeeee',
borderStyle: 'dashed',
backgroundColor: '#fafafa',
color: '#bdbdbd',
transition: 'border .3s ease-in-out'
};
const activeStyle = {
borderColor: '#2196f3'
};
const acceptStyle = {
borderColor: '#00e676'
};
const rejectStyle = {
borderColor: '#ff1744'
};
function DropzoneComponent(props) {
const onDrop = useCallback(acceptedFiles => {
console.log(acceptedFiles);
}, []);
const {
getRootProps,
getInputProps,
isDragActive,
isDragAccept,
isDragReject
} = useDropzone({
onDrop,
accept: 'image/jpeg, image/png'
});
const style = useMemo(() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}), [
isDragActive,
isDragReject,
isDragAccept
]);
return (
<div {...getRootProps({style})}>
<input {...getInputProps()} />
<div>Drag and drop your images here.</div>
</div>
)
}
export default DropzoneComponent;
此代码将产生以下结果:
更改接受和拒绝组件的外观有助于向用户提供有关其文件是否有效的反馈。
第 4 步 – 添加图像预览
预览是在组件中拖放的图像的副本。这有助于向用户提供视觉反馈以验证他们选择的图像文件的内容。
预览7.0.0版本中去除,然而,文档提供用于与的组合readding它的替代Object.assign()
和URL.createObjectURL()
。
重新访问DropzoneComponent
并修改它以使用preview
:
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDropzone } from 'react-dropzone';
const baseStyle = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '20px',
borderWidth: 2,
borderRadius: 2,
borderColor: '#eeeeee',
borderStyle: 'dashed',
backgroundColor: '#fafafa',
color: '#bdbdbd',
transition: 'border .3s ease-in-out'
};
const activeStyle = {
borderColor: '#2196f3'
};
const acceptStyle = {
borderColor: '#00e676'
};
const rejectStyle = {
borderColor: '#ff1744'
};
function DropzoneComponent(props) {
const [files, setFiles] = useState([]);
const onDrop = useCallback(acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
}, []);
const {
getRootProps,
getInputProps,
isDragActive,
isDragAccept,
isDragReject
} = useDropzone({
onDrop,
accept: 'image/jpeg, image/png'
});
const style = useMemo(() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}), [
isDragActive,
isDragReject,
isDragAccept
]);
const thumbs = files.map(file => (
<div key={file.name}>
<img
src={file.preview}
alt={file.name}
/>
</div>
));
// clean up
useEffect(() => () => {
files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
return (
<section>
<div {...getRootProps({style})}>
<input {...getInputProps()} />
<div>Drag and drop your images here.</div>
</div>
<aside>
{thumbs}
</aside>
</section>
)
}
export default DropzoneComponent;
注意:为避免内存泄漏,您需要调用URL.revokeObjectURL(file.preview)
以避免不必要地存储预览。
现在,无论何时删除一个(或多个)文件,该文件都会附加到状态并显示预览。
结论
在本教程中,您react-dropzone
了解了以及如何在 React 应用程序中使用它来为文件上传提供高级拖放功能。
如果您想了解有关 React 的更多信息,请查看我们的How To Code in React.js系列,或查看我们的 React 主题页面以获取练习和编程项目。