#javascript #html #reactjs
#javascript #HTML #reactjs
Вопрос:
Мне нужно перечислить длинный список имен на моей странице, в то время как сначала показывать все имена нежелательно. Поэтому я пытаюсь добавить к ней кнопку расширения.
Однако использование кнопки сохранит фокус браузера на этой кнопке после ее нажатия, оставив положение кнопки неизменным на экране, пока имя было вставлено перед этой кнопкой.
С другой стороны, использование любого, не фокусируемого элемента (например, div с функцией onclick) приведет к желаемому поведению, но вообще потеряет доступность. Сделать «кнопку» только интерактивной, но не фокусируемой.
Как мне сделать так, чтобы кнопка была сброшена в конец списка, как это делает блок snippet div? Или есть лучший выбор для расширения существующего списка?
const myArray = [
'Alex',
'Bob',
'Charlie',
'Dennis',
'Evan',
'Floron',
'Gorgious',
'Harris',
'Ivan',
'Jennis',
'Kurber',
'Lowrance',
]
const ExpandList = (props) => {
const [idx, setIdx] = React.useState(8)
const handleExpand = e => {
setIdx(idx 1)
}
return <div className='demo'>
<h1>Name List</h1>
{myArray.slice(0,idx).map(
name => <p key={name}>{name}</p>
)}
<div>
<button onClick={handleExpand} children='Button Expand' className='pointer' />
<div onClick={handleExpand} className='pointer'>Div Expand</div>
</div>
</div>
}
ReactDOM.render(<ExpandList/>, document.getElementById('root'))
.demo>p {
display: block;
padding: 20px;
color: #666;
background: #3331;
}
.demo>div>div {
display: flex;
padding: 15px;
margin-left: auto;
color: #666;
background: #3331;
}
.pointer {
cursor: pointer;
}
.pointer:hover {
background-color: #6663;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id='root' class='demo'>hello</div>
Комментарии:
1. размыть кнопку при нажатии и вставить содержимое после этого?
2. @0x2D9A3 Спасибо за предложение. Это должно сработать, но это также усложняет логику, поэтому в настоящее время я не рассматриваю возможность изменения порядка элементов.
3. Вы можете попробовать увеличить
idx
с небольшой задержкой, например, так:setTimeout(() => setIdx(idx 1), 0);
. (Кстати, какой браузер вы используете, потому что я не могу воспроизвести проблему в Chrome или Firefox при запуске вашего фрагмента кода)4. Chrome
86.0.4240.75
и Windows 10 (2004), а также Edge (Chromium). Отключение всех pulgin. (Удивительно, что это зависит от аппаратного обеспечения / платформы?)5. Ах, теперь я смог воспроизвести это в Edge.
setTimeout
действительно, не сработало. Я бы либо выбралe.target.blur()
ваш обработчик кликов, либо встроил его следующим образом:<button onClick={(ev) => { ev.target.blur(); handleExpand(ev)}}
Ответ №1:
Удаление фокуса с кнопки в обработчике кликов, вероятно, является наиболее элегантным подходом : e.target.blur()
. Он будет работать с любым элементом HTML, независимо от того, является ли он фокусируемым или нет (как div
в вашем случае).
const myArray = [
'Alex',
'Bob',
'Charlie',
'Dennis',
'Evan',
'Floron',
'Gorgious',
'Harris',
'Ivan',
'Jennis',
'Kurber',
'Lowrance',
]
const ExpandList = (props) => {
const [idx, setIdx] = React.useState(8)
const handleExpand = e => {
e.target.blur()
setIdx(idx 1)
}
return <div className='demo'>
<h1>Name List</h1>
{myArray.slice(0,idx).map(
name => <p key={name}>{name}</p>
)}
<div>
<button onClick={handleExpand} children='Button Expand' className='pointer' />
<div onClick={handleExpand} className='pointer'>Div Expand</div>
</div>
</div>
}
ReactDOM.render(<ExpandList/>, document.getElementById('root'))
.demo>p {
display: block;
padding: 20px;
color: #666;
background: #3331;
}
.demo>div>div {
display: flex;
padding: 15px;
margin-left: auto;
color: #666;
background: #3331;
}
.pointer {
cursor: pointer;
}
.pointer:hover {
background-color: #6663;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id='root' class='demo'>hello</div>
Комментарии:
1. А также я заметил, что при двойном нажатии после второго щелчка он все равно будет фокусироваться на моей кнопке. Поэтому я
document.activeElement.blur()
также добавляю к потере фокуса на кнопке.
Ответ №2:
Вдохновленный @MiKo, временное отключение кнопки после нажатия и установка тайм-аута для ее добавления обратно, похоже, выполняет свою работу. Поскольку браузер теряет фокус на исходной кнопке расширения, это приведет к удалению содержимого без фокусировки на исходной кнопке:
const ExpandList = (props) => {
const [idx, setIdx] = React.useState(8)
const [showBtn, setShowBtn] = React.useState(true)
const handleExpand = e => {
setShowBtn(false)
setIdx(idx 1)
setTimeout(() => setShowBtn(true), 10)
}
return <div className='demo'>
<h1>Name List</h1>
{myArray.slice(0,idx).map(
name => <p key={name}>{name}</p>
)}
{showBtn?
<div>
<button onClick={handleExpand} children='Button Expand' className='pointer' />
<div onClick={handleExpand} className='pointer'>Div Expand</div>
</div> :
<div></div>
}
</div>
}
Но я все еще ищу метод, которому не нужно «отключать» вещь, которая должна быть там все время.
Комментарии:
1. Ого, это немного перебор! Я бы выбрал
blur()
гораздо более простое решение.2. Да, размытие более элегантно, вы хотели бы опубликовать его в качестве ответа, тогда я могу пометить его как принятый? Кроме того, в моей реальной работе с компонентом Material UI ButtonBase
e.target.blur()
необходимоe.stopPropogation()
использовать, чтобы заставить его работать.3. Опубликовано в качестве ответа. Хороший улов,
e.stopPropagation()
часто может быть хорошим дополнением при работе с кнопками и ссылками.