Говоря о разработке модальных компонентов на мобильном терминале

JavaScript Vue.js

VantЭто набор, разработанный Youzan на основеVue 2.0изMobileБиблиотека компонентов тоже наступила на немало ям в процессе разработки.Сегодня мы поговорим о разработке мобильного модального компонента (этот компонент называется на Youzan).Popup) некоторые вещи, чтобы отметить.

В любой квалифицированной библиотеке компонентов пользовательского интерфейсаModalКомпоненты должны быть одним из обязательных компонентов. Обычно он используется, когда пользователи что-то обрабатывают, но не хотят переходить на страницу, вы можете использоватьModalОткройте плавающий слой на текущей странице для выполнения соответствующей операции. По сравнению с ПК, мобильныйModalБудет больше компонентных ям.Например, проблема проникновения прокрутки не такая, как на стороне ПК.bodyдобавитьoverflow: hiddenТак просто.

содержание

1. Определение API
2. Схема горизонтальной и вертикальной центровки
3. Проклятое проникновение
Четыре,position: fixedневерный

1. Определение API

Прежде чем какой-либо компонент начнет кодирование, сначала необходимо определить API, чтобы соответствующие функции могли быть предоставлены в соответствии с API.ModalКомпоненты предоставляют следующие API:

Для более подробного ознакомления с API вы можете перейти по этой ссылке, чтобы просмотреть:Popup

2. Схема горизонтальной и вертикальной центровки

В Интернете можно найти много видов схем вертикального центрирования.

  1. абсолютный (фиксированный) + отрицательная маржа
  2. absolute(fixed) + transform
  3. flex
  4. table + vertical-align

Прежде всего, давайте поговорим о втором, который мы выбираем:absolute(fixed) + transform, это самое простое и удобное решение среди вышеперечисленных решений, а объем реализации кода очень мал. Код реализации выглядит следующим образом:

.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

ноtransformприведет к огромному,этоКонкретные детали будут подробно рассмотрены в следующих главах.

После разговора о плане, который мы выбрали, почему бы не выбрать другой план?

абсолютный (фиксированный) + отрицательная маржа

Подойдет только сцена фиксированной высоты, и от нее решительно отказаться. Если вы хотите добиться неопределенной высоты, вы должны вычислить ее через JS, что увеличивает сложность реализации.

flex

flexМакет не очень совместим с некоторыми старыми версиями браузеров Android, и ему нужно обернуть родителя, чтобы отцентрировать его по горизонтали и вертикали.

table + vertical-middle

существуетCSS2Эпоха использует эту схему для достижения вертикального центрирования, это относительно распространенная схема, недостатком которой является то, что объем реализации кода относительно велик.

3. Проклятое проникновение

Любой, кто разрабатывал компоненты мобильного пользовательского интерфейса, знает, что на мобильной стороне существует ужасная проблема проникновения прокрутки. Эту проблему можно описать так: скольжение по всплывающему окну приведет к прокрутке нижней страницы.

Погуглите онлайн滚动穿透На самом деле ключевые слова могут найти множество решений, каждое из которых имеет свои преимущества и недостатки, но решение, которое мы выбрали, было вдохновлено записью в блоге об оптимизации мобильного взаимодействия, написанной сестрой из команды (адрес записи в блоге:Fancy расширяет возможности мобильных интерактивных приложений | TinySymphony).

Конкретная идея такова: когда контейнер может скользить, если он уже находится наверху, то запрещается скользить вниз; если он внизу, то запрещается скользить вверх; когда контейнер нельзя катить, запрещается скользить вверх и вниз. Способ сделать это вdocumentмониторtouchstartа такжеtouchmoveСобытия, например при скольжении, элемент-предок не имеет скользящего элемента, и он может напрямую предотвращать всплытие; в противном случае судить о направлении скольжения пальца, если он скользит вниз, судить, сдвинулся ли он в нижнюю часть скольжения элемент, и если он достиг нижней части, предотвратите всплытие и проведите вверх аналогичным образом. Конкретная реализация кода может видеть следующий код:

const _ = require('src/util')
export default function (option) {
  const scrollSelector = option.scroll || '.scroller'
  const pos = {
    x: 0,
    y: 0
  }

  function stopEvent (e) {
    e.preventDefault()
    e.stopPropagation()
  }

  function recordPosition (e) {
    pos.x = e.touches[0].clientX
    pos.y = e.touches[0].clientY
  }

  function watchTouchMove (e) {
    const target = e.target
    const parents = _.parents(target, scrollSelector)
    let el = null
    if (target.classList.contains(scrollSelector)) el = target
    else if (parents.length) el = parents[0]
    else return stopEvent(e)
    const dx = e.touches[0].clientX - pos.x
    const dy = e.touches[0].clientY - pos.y
    const direction = dy > 0 ? '10' : '01'
    const scrollTop = el.scrollTop
    const scrollHeight = el.scrollHeight
    const offsetHeight = el.offsetHeight
    const isVertical = Math.abs(dx) < Math.abs(dy)
    let status = '11'
    if (scrollTop === 0) {
      status = offsetHeight >= scrollHeight ? '00' : '01'
    } else if (scrollTop + offsetHeight >= scrollHeight) {
      status = '10'
    }
    if (status !== '11' && isVertical && !(parseInt(status, 2) & parseInt(direction, 2))) return stopEvent(e)
  }
  document.addEventListener('touchstart', recordPosition, false)
  document.addEventListener('touchmove', watchTouchMove, false)
}

Четыре,position: fixedневерный

С точки зрения фронтенд-инженеров,position: fixedОн всегда позиционируется относительно области просмотра браузера. Однажды вы применили к родительскому элементу элемент с фиксированным позиционированиемtransformКогда вы обновляете браузер, чтобы увидеть последний эффект страницы, вы обнаружите, что элемент с фиксированным положением расположен относительно родительского элемента. Вы чувствуете, что ваши взгляды на жизнь рухнули?

Эта проблема в настоящее время доступна только в браузере Chrome/браузере FireFox. также далChromeСообщить об ошибке:Fixed-position element uses transformed ancestor as the container, но до сих пор не решен.

Например следующий код:

<style>
  body {
    padding: 50px;
  }
  .demo {
    background: #ccc;
    height: 100px;
    transform: scale(1);
  }
  .fixed-box {
    position: fixed;
    top: 0;
    left: 0;
    width: 100px;
    height: 100px;
    background: red;
  }
</style>

<div class="demo">
  <div class="fixed-box"></div>
</div>

схема вертикальной центровкиposition: fixed + transformвыбор привел кModalЯма в использовании компонентов. когда мыModalКомпонент вложен вModal, внутреннийModalотносительно внешнийModalвместо области просмотра браузера. Это также ограничивает насModalСценарий использования, если вы хотите реализовать вложенныеModal, надо выбирать другие схемы центровки по вертикали, а там что-то выиграешь.

оposition: fixedДополнительные сведения об ошибке см. в следующих сообщениях блога:

Суммировать

Разработать библиотеку компонентов непросто, а разработать библиотеку мобильных компонентов еще сложнее. По сравнению со стороной ПК, в библиотеке мобильных компонентов будет больше замечательных ям. Столкнувшись с ямой, вы должны решить пересечь ее, а не убежать, поэтому у нас есть эта статья, и у нас будет несколько вводных в будущем.VantПожалуйста, ожидайте ям, обнаруженных во время разработки библиотеки компонентов, или некоторых статей, связанных с оптимизацией.

Если вы считаете, что этой статьи недостаточно, перейдите на Github для полной реализации исходного кода:popup.

Эта статья была впервые опубликована вБлог о технологиях Youzan.