Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CodeFest 2018. Тим Чаптыков и Артур Стамбульцян (ВКонтакте) — Мимикрируем под нативные приложения с React

CodeFest 2018. Тим Чаптыков и Артур Стамбульцян (ВКонтакте) — Мимикрируем под нативные приложения с React

Посмотрите выступление Тима и Артура: https://2018.codefest.ru/lecture/1292/

У нас есть клиенты для iOS и Android. Мы стараемся релизиться как можно чаще, но частота обновлений клиентов все равно сильно уступает релизам в вебе. Поэтому было решено некоторые разделы клиентов, которые часто требуют правок, сделать в формате веб-приложений, которые открываются на веб-вью, не уводя пользователей в браузер. Мы расскажем вам про библиотеку компонентов, на основе которой можно просто и быстро создавать интерфейсы, которые внешне практически неотличимы от наших мобильных клиентов, а также осветим основные проблемы, возникшие в процессе разработки.

CodeFest

April 05, 2018
Tweet

More Decks by CodeFest

Other Decks in Programming

Transcript

  1. Web Хотим открывать в браузере Кроссплатформенность Хотим использовать один cлой

    представления 
 на всех платформах Открытость Мечтаем дать доступ сторонним разработчикам
  2. Props <Gallery 
 data={[ 
 { 
 source: 'image1.jpg', 


    altText: 'Image 1' 
 }, 
 { 
 source: 'image2.jpg', 
 altText: 'Image 2' 
 }, 
 { 
 source: 'image3.jpg', 
 altText: 'Image 3' 
 } 
 ]} 
 />
  3. Children <Gallery> 
 <img src="image1.jpg" alt="Image 1" /> 
 <img

    src="image2.jpg" alt="Image 2" /> 
 <img src="image3.jpg" alt="Image 3" /> 
 </Gallery>
  4. <Gallery /> <Group 
 title={title}
 description={description}
 > 
 <Gallery style={styles}>

    
 <img src="image1.jpg" /> 
 <img src="image2.jpg" /> 
 <img src="image3.jpg" /> 
 </Gallery> 
 </Group>
  5. Гибкость <Gallery> 
 <div> 
 <h1>Hello, World!</h1> 
 </div> 


    <img src="image1.jpg" alt="Image 1" /> 
 <img src="image2.jpg" alt="Image 2" /> 
 </Gallery>

  6. Для разработчиков <View activePanel={state.activePanel}> 
 <ScrollView id="settings" /> 
 <ScrollView

    id="account" /> 
 </View> 
 
 // Когда нужно будет сменить панель
 this.setState({ activePanel: 'account' }); 
 
 

  7. Интерфейс — панели передаются как children Порядок — задекларирован в

    children Производительность — отображается 1—2 панели
  8. Обычное состояние <section> 
 <article className="Panel" /> 
 <article className="Panel

    Panel--active" /> 
 <article className="Panel" /> 
 <article className="Panel" /> 
 </section>
  9. Переход <section> 
 <article className="Panel" /> 
 <article className="Panel Panel--prev"

    /> 
 <article className="Panel" /> 
 <article className="Panel Panel--next" /> 
 </section>
  10. React.cloneElement React.cloneElement(panel, { isPrev: panel.id === this.state.prevPanel, isNext: panel.id ===

    this.state.nextPanel, isActive: panel.id === this.state.activePanel, isSwiping: this.state.isSwiping });
  11. Если дизайнер передумал и решил добавить кнопке отступ. И сделать

    эту кнопку красной. На зеленом фоне. С подчеркиванием. <Button 
 type="cell" 
 style={{ 
 color: 'red', 
 backgroundColor: '#8ffe09', 
 marginTop: 8, 
 textDecoration: 'underline' 
 }}> 
 Account
 </Button>
  12. Спустя месяц… <input 
 onChange={this.props.onChange} 
 onBlur={this.props.onBlur} 
 onFocus={this.props.onFocus} 


    onKeyDown={this.props.onKeyDown} 
 onKeyUp={this.props.onKeyUp} 
 value={this.props.value} 
 disabled={this.props.disabled} 
 readonly={this.props.readonly} 
 style={this.props.style} 
 className={this.props.className} 
 id={this.props.id} 
 placeholder={this.props.placeholder} 
 />
  13. И где-то рядом PropTypes static propTypes = { 
 onChange:

    PropTypes.func, 
 onBlur: PropTypes.func, 
 onFocus: PropTypes.func, 
 onKeyDown: PropTypes.func, 
 onKeyUp: PropTypes.func, 
 value: PropTypes.string, 
 disabled: PropTypes.bool, 
 readonly: PropTypes.bool, 
 style: PropTypes.object, 
 className: PropTypes.string, 
 id: PropTypes.string, 
 placeholder: PropTypes.string
 };
  14. ...restProps const { onChange, ...restProps } = this.props; 
 


    return ( <input {...restProps} onChange={this.onChange} /> );
 

  15. Что умеет — Подписываться на touch-события — Засекать время и

    координаты — Обрабатывать multitouch — Определять ось движения (X, Y)
  16. Slider — 165 LOC Gallery — 386 LOC Tappable —

    298 LOC C учетом пустых строк, комментариев и деклараций propTypes.
  17. Решение Запоминаем позицию fixed блоков 
 до трансформации и на

    время перехода превращаем их в absolute с указанием 
 свойства top.
  18. Решение if (scrollTop <= 0) { 
 el.scrollTop = 1;

    
 } else if (scrollTop >= scrollHeight - offsetHeight) { 
 el.scrollTop = scrollHeight - offsetHeight - 1; 
 }
  19. Решение <meta name="viewport" content="viewport-fit=cover"> /* Используем в CSS */ .Header

    { 
 padding-top: env('safe-area-inset-top'); 
 } 
 .Footer { 
 padding-bottom: env('safe-area-inset-bottom'); 
 }
  20. Scale .a { 
 height: 1px; 
 background: #ccc; 


    transform: scaleY(50%); 
 transform-origin: 0 0; 
 }
  21. Gradient .a { 
 height: 1px; 
 background: linear-gradient( to

    top, transparent 50%, #ccc 50% ); 
 }