Предотвращение фокусировки на кнопке расширения после вставки содержимого в React

#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() часто может быть хорошим дополнением при работе с кнопками и ссылками.