React.js


React.js

Библиотека для построения UI-слоя

AKA: V in MVC

Роуты

Модели

Биндинги

Вотчеры

Шаблоны

Разрабатывается инженерами Facebook

В бою на Facebook.com и Instagram.com

How Instagram.com works

React.js

  Реализует однонаправленный реактивный поток данных
Проще традиционного дата-биндинга

Key concepts

Компоненты    Шаблоны
Re-render    Мутация
Виртуальный DOM
Синтетические события

View + Template


Шаблоны и логика UI сильно связаны
Имеют одну ответственность

Одна ответственность разделяется на две технологии
и лишнии абстракции

= Component

Spaghetti code!?

Оставляйте свои компоненты небольшими

Link

Многие SPA фреймворки для связи модели с частью UI  используют bindings, observers, templates...

В React есть только состояние

Binding / Observers

Должны мутировать модель для передачи изменений в представление
Каждая мутация может запускать ненужные observers (Run Loop / Digest loop)

React is functional

f(state, props) = UI Fragment

или по-хорошему
f(props) = UI Fragment

  1. Идемпотентность
  2. Неизменяемость
  3. Тестабильность

Re-render на любое изменение

Разработка UI сложна по причине огромного количества состояний
  • Много элементов
  • Вариантов дизайна
  • Непредсказуемое окружение
  • Изменяемый DOM
  • Пользовательский ввод
  • и т.д...

Re-render на любое изменение

Изменение данных причина всех зол

в 90-е было легко

Простое обновление страницы на любое изменение данных

Re-render на любое изменение


Без observers
Без магических дата-биндингов
Без dirty checking моделей
Без $apply() и $digest()

Просто и надежно

 Перестроение DOM?


Virtual DOM

In-memory структура данных
Синтетическая система событий (обертка)
Оптимизирован для эффективности и объема используемой памяти

React`s architecture looks a lot like the Doom 3 engine


Рендер из данных в VDOM быстрый
Нет конкатенации строк

на каждое изменение...

  1. Строится новое дерево Virtual DOM
  2. Сравнивается со старым
  3. Высчитывается кратчайший путь преобразования
  4. Добавляется в очередь
  5. Пакетный рендер изменений в настоящий DOM

Bonus

Серверный рендер в Node.js, PHP, Java, etc...
Поддержка SVG, VML, Canvas

Синтетические события

React имплементирует собственную событийную систему
Единственный обработчик на корневом компоненте (делегирование)
Нормализирует события между разными браузерами
Отделяет события от DOM

Component code

var Hello = React.createClass({

    getInitialState: function() {
        return { count: 0 }
    },

    render: function() {
        return React.DOM.div(
            { className: "name", onClick: this.handleClick },
                React.DOM.span("Hello, " + this.props.name + "!"),
                React.DOM.strong("clicked " + this.state.count + " times")
        )
    },

    handleClick: function() {
        this.setState({ count: this.state.count + 1 })
    }
})

Возвращаемое значение не является строкой
или DOM нодой, это легковесное описание того, как должен выглядеть DOM.

 Component code (JSX)

var Hello = React.createClass({

    getInitialState: function() {
        return { count: 0 }
    },

    render: function() {
        return <div className="name" onClick={this.handleClick}>
            <span>Hello, {this.props.name}!</span>
            <strong>clicked {this.state.count} times</strong>
        </div>
    },

    handleClick: function() {
        this.setState({ count: this.state.count + 1 })
    }
})

JSX легкий сахар который конвертируется в JS

JSX

Доступность шаблонов и сила JavaScript
Делает React более доступным верстальщикам

Composition

var Counter = React.createClass({
    render: function() {
        if (!this.props.count) return null
        return <strong>clicked {this.props.count} times</strong>
    }
})
var Hello = React.createClass({

    getInitialState: function() {
        return { count: 0 }
    },

    render: function() {
        return <div className="name" onClick={this.handleClick}>
            <span>Hello, {this.props.name}!</span>
            <Counter count={this.state.count} />
        </div>
    },

    handleClick: function() {
        this.setState({ count: this.state.count + 1 })
    }
})

Render code

React.render(Hello({ name: 'TCS' }), document.body)
response.send(React.renderToString(Hello({ name: 'TCS' })))

Lifecycle


Made with Slides.com