preactjs, дважды включенный тоглер
Я столкнулся со странным поведением с preactjs, странным, потому что со мной никогда не случалось такое с реакцией. Посмотрите на эту скрипку:
Это супер простой компонент с кнопкой, которая действует как переключатель. Пожалуйста, откройте консоль браузера и посмотрите журналы консоли.
Изначально реквизит активного состояния ложный -> НЕАКТИВНЫЙ. Когда вы в первый раз щелкаете знак вопроса, как и ожидалось, вызывается функция переключения, целью которой является кнопка (примечание: в моем локальном окружении целью события оказывается элемент ".help-overlay" (который должен отображаться только после изменения состояния) есть идеи?)
Затем состояние active prop устанавливается в true, компонент снова отображается -> ACTIVE в консоли, и кнопка изменяется.
Теперь нажатие на кнопку запускает событие onclick дважды, и, очевидно, ничего не меняется.
Я знаю, что эти вещи каким-то образом связаны с распространением событий, и фактически добавление e.stopPropagation() в начале функции переключения делает свою работу.
Но то, что я не понимаю, почему! Я имею в виду, событие должно распространяться вверх через дом, почему, черт возьми, должен снова запустить тот же обработчик onclick на том же элементе?
Вот почему я не прошу решения, но объяснения того, что происходит, что я не могу понять.
Большое спасибо.
Я выложу здесь код компонента рекламы в скрипке.
const { h, render, Component } = preact; // normally this would be an import statement.
class Help extends Component {
constructor () {
super()
this.state = {active: false}
this.toggle = this.toggle.bind(this)
}
toggle (e) {
console.log('ONCLICK', new Date().getTime(), e.target)
this.setState(state => ({active: !state.active}))
}
render () {
if (!this.state.active) {
console.log('NOT ACTIVE')
return (
<div class='help-btn' onClick={this.toggle}>?</div>
)
} else {
console.log('ACTIVE')
return (
<div class='help-overlay'>
<div class='help-btn' onClick={this.toggle}>✕</div>
</div>
)
}
}
}
// render an instance of Clock into <body>:
render(<Help />, document.body);
1 ответ
div с оверлейным классом в одном dom, а не в другом, создает vdom diff, который запускает триггер для повторного рендеринга. Я обернуть оба div с родительским div содержит класс условного наложения, и он работает, как ожидалось.
.help-btn {
background: #000;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
}
.help-overlay {
background: rgba(0, 0, 0, .7);
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: 9;
}
/** @jsx h */
const { h, render, Component } = preact; // normally this would be an import statement.
class Help extends Component {
constructor () {
super()
this.state = {active: false};
}
toggle (e,isActive) {
console.log('ONCLICK', new Date().getTime(), e.target)
this.setState({active:!isActive});
}
render (props,{active}) {
return (
<div class={active ? "help-overlay" : "" }>
{!active && <div class='help-btn' onClick={e => this.toggle(e,false)}>?</div>}
{active && <div class='help-btn' onClick={e => this.toggle(e,true)}>✕</div>}
</div>
)
}
}
// render an instance of Clock into <body>:
render(<Help />, document.body);
jsfiddle - http://jsfiddle.net/nhkz4feq/