#javascript #reactjs #events #ecmascript-6
#javascript #reactjs #Мероприятия #ecmascript-6
Вопрос:
У меня есть элемент ввода, который отображается в зависимости от условия.
render() {
const {
isNameInputVisible,
name
} = this.state;
return (
<div>
{isNameInputVisible ? (
<input
onChange={this.handleNameChange}
ref={this.nameInput}
type="text"
value={name}
/>
) : (
<h1
className="list-header__heading"
onClick={this.handleNameInputVisibility}
>
{name}
</h1>
)}
</div>
)
В принципе, я хочу прослушать щелчок по документу, чтобы скрыть ввод всякий раз, когда пользователь нажимает за пределами этого элемента ввода.
Прямо сейчас я делаю это:
componentDidMount() {
document.addEventListener('mousedown', this.handleClick);
}
handleClick = event => {
//do some logic
};
Но мне было интересно, правильно ли это, потому что событие существует и срабатывает,
даже когда элемент не отображается.
Итак, я попробовал это:
componentDidUpdate () {
const {isNameInputVisible} = this.state;
isNameInputVisible amp;amp; document.addEventListener('mousedown', this.handleClick);
}
Но это не работает.
Вопрос 1: каков правильный способ прикрепления событий к документу, когда это зависит от других условно отображаемых элементов??
Вопрос 2: каков правильный способ прикрепления событий, например, таких, как escape press, для закрытия диалоговых окон, которые выходят и т.д.??
Комментарии:
1. Добавьте прослушиватель в componentDidMount. Проверьте
target
в обработчике. Обязательно удалите прослушиватель вcomponentWillUnmount
2. вот как я делаю это прямо сейчас 🙂 Но обработчик срабатывает, даже когда мне это не нужно, потому что ввод не виден. Вот почему мне интересно, правильно ли это?
3. Может сделать ввод компонентом
Ответ №1:
Вам нужно добавить прослушиватель событий в componentDidMount
метод, только если ссылка на условно отображаемый элемент существует. Вы можете определить, была ли ссылка прикреплена к элементу с помощью this.refName.current
.
Самое важное здесь то, что input
элемент получает свои собственные методы жизненного цикла вместо того, чтобы делиться ими с более крупным компонентом. Перемещая input
элемент в его собственный компонент с его собственными методами жизненного цикла, эти методы будут срабатывать только при создании и удалении input
.
// App.jsx
import React from "react"
import ReactDOM from "react-dom"
import CustomInput from "./CustomInput"
class App extends React.Component {
constructor(props) {
super(props)
this.inputRef = React.createRef()
this.toggleInput = this.toggleInput.bind(this)
this.state = {
inputVisible: false
}
}
toggleInput(e) {
this.setState(prevState => ({
inputVisible: !prevState.inputVisible
}))
}
render() {
const { inputVisible } = this.state
return (
<div>
<input type="button" value="toggle input" onClick={this.toggleInput} />
{ inputVisible
? <CustomInput />
: <p>Input is not visible</p>
}
</div>
)
}
}
const rootElement = document.getElementById("root")
ReactDOM.render(<App />, rootElement)
// CustomInput.jsx
import React from "react"
export default class CustomInput extends React.Component {
constructor(props) {
super(props)
this.inputRef = React.createRef()
}
componentDidMount() {
this.inputRef.current amp;amp;
document.addEventListener("mousedown", this.handleClick)
}
componentWillUnmount() {
document.removeEventListener("mousedown", this.handleClick)
}
handleClick(e) {
console.log("clicked")
}
render() {
return (
<input type="text" ref={this.inputRef} />
)
}
}
Попробуйте это здесь
Комментарии:
1. Это не сработает. как от deafult. Ввод невидим, поэтому react не создаст ссылку на него. Я попробовал ту же самую оценку в componentDidMount(). Вот так: componentDidMount() { this.inputRef.current amp;amp; document.addEventListener()….. } но при таком подходе, даже когда состояние было обновлено до значения isInputVisible равным true, EventListener не был прикреплен к документу.
2. Это связано с тем, что ссылка должна быть прикреплена к условному элементу с использованием методов жизненного цикла компонента, которые вызываются после создания входных данных. Как только вы перемещаете входной элемент в его собственный компонент с его собственными методами жизненного цикла, он работает отлично. Я обновлю свой ответ этим.