需求
本周要实现一个上传图片的功能,简化应用场景:点击上传图片,增加一张图片,hover图片,出现删除按钮,点击删除按钮,删除该图片。
效果
delete.gif分析
规划级别:图片+删除按钮作为一个子组件(此处是Image),整体作为一个父组件
注意的点:生成的组件是一个数组,为了准确的删掉对应项,生成对应编号。点击删除按钮反馈当前编号,然后进行删除。由于子组件生成后,index属性是固定的,当删除元素的时候就不知道是哪个元素,所以可以通过自定义属性data-index来获取子组件的编号。
具体逻辑:数据驱动,使用数据展示界面,在state里保存要展示的数据,在render里动态生成子组件,render里的子组件会根据数据的变化而刷新。
实现
子组件
export default class Image extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
let {
index,
deleteImage,
} = this.props;
return (
<div
className="upload-pic">
<span className="upload-pic-left"/>
<div className="upload-pic-right">
<img
className="upload-pic-thumbnail"
/>
<span className="upload-pic-mask"
onClick={deleteImage}
data-index={index}
/>
</div>
</div>
)
}
}
渲染组件:
render(){
let {
fileList
} = this.state;
return(
{
fileList.map((item, index) => {
return (
(
<Image
key={index}
index={index}
src={item[0].thumb}
alt={item[0].name}
deleteImage={this.deleteImage}/>
)
)
})
}
)
}
添加图片:
// 添加图片
addImage(e) {
let {
fileList
} = this.state;
e.preventDefault();
// 判断是否能上传
this.getUpload(e);
// 判断是否满足条件
if (isUploadSize && isUploadLengthLimit) {
fileList.push(globalFileObj);
this.setState({
fileList: fileList
});
} else {
console.log('失败');
}
};
鼠标事件
父组件代码如下:
// 鼠标移进
handleMouseOver(e) {
this.isShowMask(e,true);
}
// 鼠标移出
handleMouseOut(e) {
this.isShowMask(e,false);
}
// 是否显示遮罩层
isShowMask(e,bool){
e.preventDefault();
let index = e.currentTarget.getAttribute("data-index");
let {fileList} = this.state;
fileList[index].isHover = bool;
this.setState({
fileList: fileList
})
}
render(){
let {
fileList
} = this.state;
return(
{
fileList.map((item, index) => {
return (
(
<Image
key={index}
index={index}
src={item[0].thumb}
alt={item[0].name}
isHover={item.isHover}
handleMouseOver={this.handleMouseOver}
handleMouseOut={this.handleMouseOut}
deleteImage={this.deleteImage}/>
)
)
})
}
)
}
e.target和e.currentTarget的区别
此处需要注意一下e.target和e.currentTarget的区别,e.currentTarget指的是注册事件对象,e.target指的是实际触发事件对象,简单来说,当使用e.target的时候,虽然事件绑定在父级上,但是当经过子节点的时候,e.target指向子节点,而使用e.currentTarget,始终指向注册事件对象(此处为父节点)。
如何区分悬浮在哪个子组件上
当获取到每个子组件标示的data-index之后,利用fileList[index].isHover = false; 并将标识传给子组件(此处是isHover={item.isHover}),子组件再根据标识,做出一些特殊行为。
子组件代码如下:
export default class Image extends Component {
render() {
let {
src,
alt,
index,
deleteImage,
handleMouseOver,
handleMouseOut,
isHover
} = this.props;
return (
<div
className={`upload-pic ${isHover ? 'upload--mask' : ''}`}>
<span className="upload-pic-left"/>
<div className="upload-pic-right"
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut}
data-index={index}
>
<img
className="upload-pic-thumbnail"
src={src}
alt={alt}
/>
<span className="upload-pic-mask"
onClick={deleteImage}
data-index={index}
/>
</div>
</div>
)
}
}
删除图片:
使用splice(index,1)删除当前元素,改变原数组,且更新state
// 删除图片
deleteImage(e) {
e.preventDefault();
let {fileList} = this.state;
let index = e.target.getAttribute("data-index");
fileList.splice(index, 1);
this.setState({
fileList: fileList
})
}
网友评论