html - 我想在 Reactjs 中添加 addEventListener() 如果我点击这个模型之外,模型就会关闭
问题描述
class Model extends Component {
render() {
return (
<ProductConsumer>
{(value) => {
const {modelOpen, closeModel} = value;
const{img, title, price} = value.modelProduct;
if (!modelOpen) {
return null;
}
else {
return (
<ModalContainer>
<div className="container">
<div className="row">
<div id="model" className=" cl-8 mx-auto xolo-md-6 collg-4 text-center text-capitalize p-5">
<h5> Item added to cart </h5>
<img src={img} className="img-fluid" alt="product" />
<h5> {title} </h5>
<h5 className="text-muted"> price : $ {price} </h5>
<Link to="/">
<ButtonContainer onClick = {() => closeModel()}>
continue shopping
</ButtonContainer>
</Link>
<Link to="/cart">
<ButtonContainer cart onClick={() => closeModel()}>
go to cart
</ButtonContainer>
</Link>
</div>
</div>
</div>
</ModalContainer>
);
}}
}
</ProductConsumer>
);
}
}
export default Model;
解决方案
您可以使用以下组件来检查点击是在外部还是内部。
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export default class OutsideClick extends Component {
constructor (props) {
super(props)
this.getContainer = this.getContainer.bind(this)
this.isTouch = false
this.handle = this.handle.bind(this)
this.checkIfClickWithinListenBoundary = this.checkIfClickWithinListenBoundary.bind(this);
this.checkifClickWithinIgnoreBoundary = this.checkifClickWithinIgnoreBoundary.bind(this);
}
componentDidMount () {
document.addEventListener('touchend', this.handle, true)
document.addEventListener('click', this.handle, true)
}
componentWillUnmount () {
document.removeEventListener('touchend', this.handle, true)
document.removeEventListener('click', this.handle, true)
}
getContainer (ref) {
this.container = ref
}
checkIfClickWithinListenBoundary(node) {
if (!this.props.listenClickWithinClass) {
return true;
}
const el = document.querySelector(`.${this.props.listenClickWithinClass}`)
if (!el) {
return el.contains(node)
}
return false
}
checkifClickWithinIgnoreBoundary(node) {
if (!this.props.ignoreClickWithinClass) {
return true;
}
const el = document.querySelector(`.${this.props.ignoreClickWithinClass}`)
if (el) {
return !el.contains(node)
}
return false
}
handle (e) {
if (e.type === 'touchend') {
this.isTouch = true
}
if (e.type === 'click' && this.isTouch) {
return
}
const { onClickOutside } = this.props
const el = this.container
if (!el.contains(e.target) && this.checkIfClickWithinListenBoundary(e.target) && this.checkifClickWithinIgnoreBoundary(e.target)) {
onClickOutside(e)
}
}
render () {
const {
children, onClickOutside, listenClickWithinClass, ignoreClickWithinClass, ...props
} = this.props
return <div {...props} ref={this.getContainer}>{children}</div>
}
}
OutsideClick.propTypes = {
onClickOutside: PropTypes.func.isRequired,
listenClickWithinClass: PropTypes.string,
ignoreClickWithinClass: PropTypes.string,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
}
OutsideClick.defaultProps = {
children: null,
listenClickWithinClass: null,
ignoreClickWithinClass: null
}
你可以使用这种方式。
return (
<OutsideClick onClickOutside={() => this.closeModel()} >
<ModalContainer>
.......
</ModalContainer>
</OutsideClick>
)
推荐阅读
- pandas - Dataframe - 如何将日期时间转换为时间戳
- java - 如何在我的自动化脚本中允许 chrome 中的广告?
- python - 我用 tensorflow 写的图像分类模型学不会
- android - 如何在测试期间通过自定义导航选项
- javascript - 将原型函数应用于循环中的 2 个不同对象仅适用于第二个对象
- iis - 使用 SSL 在本地 LAN 上路由
- bash - ahk 在 bash 脚本中发送替代方案
- java - 每天在特定时间重置变量并触发通知 - 即使应用程序关闭
- python - 将经纬度坐标的 CSV 文件输入 API 以提取天气数据?
- unity3d - 通过旋转向对象施加力