Создание собственной библиотеки валидации на React дополнительные функции (часть 2) Javascript


Оглавление (нажмите, чтобы открыть):

Создание собственной библиотеки валидации на React: дополнительные функции (часть 2) Javascript

Реализации валидации форм в React.js предусматривает проверку их введенных значений, и если эти значения сооветстуют требованиям, тогда происходит изменение состояния компонента. Так, определим следующую страницу index.html:

Здесь добавлено поле для ввода возраста. Дополнительные значения nameValid и ageValid позволяют установить корректность введенных имени и возраста соответственно. Эти значения понадобятся для стилизации полей. Так, если введенное значение некорректно, то поле ввода будет иметь красную границу, иначе зеленую.

При определении поля ввода каждое поле связывается с определенным значением в state:

И для каждого поля ввода определен свой обработчик onChange, в котором происходит валидация и изменение введенного значения:

Валидация сложных форм React. Часть 1

Для начала надо установить компонент react-validation-boo, предполагаю что с react вы знакомы и как настроить знаете.

npm install react-validation-boo

Чтобы много не болтать, сразу приведу небольшой пример кода.

Давайте разберём этот код.

Начнём с функции connect, в него мы передаём наши правила валидации и другие дополнительные параметры. Вызвав этот метод мы получаем новую функцию в которую передаём наш компонент(MyForm), чтобы он получил в props необходимые методы работы с валидацией форм.

В функции render нашего компонента мы возвращаем компонент Form который соединяем с правилами валидации connect= . Эта необходимая конструкция для того чтобы Form знал как валидировать вложенные компоненты.
поле ввода которое мы будем проверять, правила проверки мы передали connect в свойстве rules. В нашем случае это name не должно быть пустым(required).

Также мы в connect передали middleware: logger, для того чтобы в консоли увидеть как происходит валидация.

В props нашего компонента мы получили набор функций:

  1. vBoo.isValid() — возвращает true, если все компоненты ввода прошли валидацию
  2. vBoo.hasError(name) — возвращает true, если компонент со свойством name не валидин
  3. vBoo.getError(name) — для компонента со свойством name, возвращает текст ошибки

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

В данном примере чекбокс remember на русском язык обязательно должен быть установлен required, а на других он всегда валиден valid.

Также мы передали в connect функцию labels(lang), которая возвращает название полей в читаемом виде.

В props вашего компонента, есть функция getLabel(name), которая возвращает значение переданное функцией labels или если такого значения нет, то возвращает name.

Базовые компоненты vBoo

Form, Input, InputRadio, InputCheckbox, Select, Textarea.

Правила валидации

Давайте рассмотрим как писать свои правила валидации.
Для того чтобы написать правило необходимо создать класс, который будет унаследован от класса validator.

Теперь подключим наш валидатор к форме.

Чтобы каждый раз не прописывать все ваши правила валидации, создаём отдельный файл, где они будут прописаны и подключаем его validators: `import ‘file-validation’`. А если для этой формы есть какие-то особые правила, то validators: Object.assign(<>, `import ‘file-validation’`, <. >)

Сценарии

Рассмотрим случаи когда нам необходимо менять правила валидации в зависимости от действий производимых на форме.

По умолчанию у нас сценарий, который называется default, в правилах мы можем прописать при каком сценарии проводить данную валидацию.

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

Через свойство props нашего компонента передаются функции:

  1. vBoo.setScenario(scenario) — устанавливает сценарий scenario, может быть как строка так и массив, если у нас активны сразу несколько сценариев
  2. vBoo.getScenario() — возвращает текущий сценарий или массив сценариев
  3. vBoo.hasScenario(name) — показывает установлен ли сейчас данный сценарий, name строка

Давайте в нашей форме добавим объект scenaries, в котором будем хранить все возможные сценарии, true сценарий активен, false нет.

А также функции addScenaries и deleteScenaries, которые будут добавлять и удалять сценарии.

Если у нас «семейное положение» выбрано «сожительство» или «брак», то добавляем поле комментарий и естественно это поле надо валидировать только в этом случае, сценарий ‘scenario-married‘.

Если у нас чекбокс «Дополнительно» выставлен, то добавляем дополнительные поля, которые станут обязательны для заполнения, сценарий ‘scenario-addition‘.

Чтобы не делать статью очень большой, продолжу в следующей, где напишу как создавать свои компоненты(например календарь или inputSearch) и их валидировать, как связать с redux и другое.

Валидация форм на React JS

Нам нужны формы. Больше форм.

Первой идеей было взять понятное и простое готовое решение, но, на второй взгляд, оно оказалось плохим: там используются неправильные с точки зрения архитектуры React решения: назначение props уже после создания элемента, жесткая связь между элементами. Как это обычно и бывает, неправильная архитектура ведет к неправильному поведению приложения в базовых сценариях. Представьте себе, например, форму, которая меняется динамически в зависимости от вашего ввода — это же как раз то, зачем React и сделан, именно та задача, с которой он отлично справляется.

Но не в этом случае. Если назначить props уже после создания элемента (чего делать не стоит — это, к слову, warning), они не сохранятся после пересоздания компонента, когда React решит еще раз запустить render(). Так что жесткая связь лишает главного преимущества React — реактивных view. Правильным решением было бы использовать события — они позволяют общаться элементам, не связывая их напрямую друг с другом. Всё, что для этого нужно — общая шина. Предлагаю своё решение, вы можете сразу посмотреть демо.

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

  • FormBus.Form.attachForm() — подписка формы на события, необходимо вызвать в componentWillMount компонента формы.
  • FormBus.Form.detachForm() — отписка формы от событий, необходимо вызвать в componentWillUnmount компонента формы.
  • FormBus.Form.val >field_validation .
  • FormBus.Form.val >FormBus.Input.attachField() — подписка поля ввода на события, необходимо вызвать в componentWillMount компонента ввода.
  • FormBus.Input.detachField() — отписка поля ввода от события, необходимо вызвать в componentWillUnmount компонента ввода.
  • FormBus.Input.updateField() — обновить значение поля в модели, необходимо вызвать после изменения введенного значения в поле ввода

События

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

Компонент формы

Создадим компонент формы. Он будет выполнять роль аггрегатора данных, поступающих из элементов ввода.

Компонент текстового поля

Создадим также простейший компонент с логикой текстового поля. Основная роль любого компонента ввода: при создании заявить миру о своем существовании, при кончине сообщить о ней, а также держать всех в курсе изменения значения. Всё это достигается вызовом соответствующих методов FormBus.Input в контексте текущего класса. Важно, чтобы у компонента был задан formns в свойствах, а также value в состоянии.

Собираем детали вместе

Библиотека

Использование jquery для промисов и event-emitter для событий не принципиально. Это могут быть любые промисы (например, q) и любая шина событий.

Учебник: введение в React

Данный учебник не предполагает каких-либо знаний React.

Перед тем как начнём

В данном разделе мы создадим небольшую игру. У вас может возникнуть соблазн пропустить его, так как вы не пишете игры — не делайте такое поспешное решение. Методы, которые вы здесь изучите, имеют основополагающее значение для создания любых React приложений, а их освоение даст вам глубокое понимание React.

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

Учебник состоит из нескольких разделов:

Установка. Даст вам отправную точку, чтобы следовать учебнику.

Обзор. Познакомит вас с основами React: компонентами, свойствами и состоянием.

Завершение игры. Научит вас наиболее распространенным методам разработки в React.

Добавление Time Travel. Даст вам более глубокое понимание уникальных преимуществ React.

Вам не обязательно изучать полностью все разделы, чтобы извлечь пользу из этого учебника. Постарайтесь добраться как можно дальше — даже если это одна или две главы.

Во время изучения можно копировать и вставлять код, но мы рекомендуем набирать его вручную. Это поможет вам развить мышечную память и получить более глубокое понимание происходящего.

Что мы разрабатываем?

В этом учебнике мы покажем, как создать интерактивную игру в крестики-нолики используя React.

Вы можете увидеть, что именно мы будем разрабатывать здесь: Окончательный результат. Если код для вас непонятен, или если вы не знакомы с синтаксисом, не беспокойтесь! Цель учебника — помочь вам понять React и его синтаксис.

Мы рекомендуем вам ознакомиться с игрой в крестики-нолики, прежде чем продолжить обучение. Одна из особенностей, которую вы заметите, это то, что справа от игрового поля есть нумерованный список. Данный список содержит историю всех ходов, произошедших в игре, обновляясь по ходу игры.

Наш следующий шаг — произвести необходимые настройки, чтобы вы могли начать создавать игру.

Предварительные требования

Мы предполагаем, что вы немного знакомы с HTML и JavaScript. Но даже если вы переходите с другого языка программирования, вы должны быть способны понимать то, о чем идет речь в этих главах. Мы также предполагаем, что вы знакомы с такими понятиями программирования, как функции, объекты, массивы и, возможно в меньшей степени, классы.

Если вам нужно повторить JavaScript, можно использовать данное руководство (хотя лично я предпочитаю это руководство). Обратите внимание, что в данном учебнике мы используем некоторые функции ES6 — недавней версии JavaScript: функции-стрелки, классы, операторы let и const. Вы можете использовать Babel REPL, чтобы проверить, во что компилируется код ES6.

Установка

Освоить данное руководство можно двумя способами: вы можете либо писать код в своем браузере, либо настроить локальную среду разработки на своем компьютере.

1-й вариант установки

Это самый быстрый способ начать работу!

Сначала откройте этот стартовый код в новой вкладке. Новая вкладка должна отображать пустую игровую доску в крестики-нолики и код React. В этом учебнике мы будем редактировать код React.

Теперь вы можете пропустить второй вариант установки и перейти к разделу «Обзор», чтобы приступить к обзору React.

2-й вариант: локальная среда разработки

Это исключительно по желанию и совершенно не обязательно для данного учебника!

Необязательно: инструкции для разработки локально с помощью предпочитаемого вами текстового редактора.

Данная установка потребует больше времени и сил, но позволяет вам освоить учебник, используя предпочитаемый вами редактор (например WebStorm). Выполните следующие шаги:

Убедитесь, что у вас установлена последняя версия Node.js.

Удалите все файлы в папке src/ нового проекта.

Не удаляйте всю папку src , только файлы c кодом внутри нее. На следующем шаге мы заменим эти файлы примерами, необходимыми для нашего проекта.

Добавьте файл с именем index.css в папку src/ с этим кодом CSS.

Добавьте файл с именем index.js в папку src/ с этим кодом JS.

Добавьте следующие три строки в начало файла index.js в папке src/ :

Теперь, если вы запустите npm start в папке проекта и откроете http://localhost:3000 в браузере, вы должны увидеть пустое поле крестики-нолики.

Также мы рекомендуем следовать данным инструкциям, чтобы настроить подсветку синтаксиса в вашем редакторе.

Помогите, я застрял!

Если вы застряли, посетите ресурсы сообщества поддержки. В частности, Reactiflux Chat — отличный способ быстро получить помощь. Если же вы не получили ответа или зашли в тупик, пожалуйста, сообщите нам в Git о проблеме, и мы вам поможем.

Обзор

Теперь, когда вы произвели всю необходимую установку, давайте познакомимся с React!

Что такое React?

React — это декларативная, эффективная и гибкая библиотека JavaScript для создания пользовательских интерфейсов (UI). Она позволяет вам создавать сложные UI из небольших и изолированных частей кода, называемых «компонентами».

В React есть несколько разных типов компонентов, но мы начнем с подклассов React.Component :

Cкоро мы перейдем к забавным XML-подобным тегам. Мы используем компоненты, чтобы сообщить React, что именно мы хотим видеть на экране. Когда наши данные изменятся, React будет эффективно обновлять и повторно отрисовывать наши компоненты.

Здесь ShoppingList — это класс компонента React или тип компонента React. Компонент принимает параметры, называемые props (сокращение от properties — свойства), и возвращает иерархию представлений, отображаемых с помощью метода render .

Метод render возвращает описание того, что именно вы хотите видеть на экране. React берет это описание и отображает результат. В частности, render возвращает элемент React, который и представляет собой легковесное описание того, что нужно отрисовать. Большинство разработчиков React используют специальный синтаксис под названием JSX, который облегчает написание этих структур. Синтаксис

Если вам интересно, createElement() более подробно описан в справочнике по API, но мы не будем пользоваться им в этом учебнике. Вместо него мы будем продолжать использовать JSX.

JSX включает в себя JavaScript. Вы можете поместить любые выражения JavaScript в фигурные скобки внутри JSX. Любой React элемент представляет собой объект JavaScript, который вы можете сохранить в переменной или передать куда-либо в своей программе.

Компонент ShoppingList выше отрисовывает только нативные компоненты DOM, такие как

Проверка стартового кода

Если вы собираетесь работать с учебником в своем браузере, откройте этот код в новой вкладке: стартовый код. Если вы собираетесь работать над учебником в локальной среде, откройте src/index.js в папке вашего проекта (вы уже коснулись этого файла во время установки).

Этот стартовый код является основой того, что мы строим. Мы предоставили стили CSS, так что вам нужно сосредоточиться только на изучении React и программировании игры в крестики-нолики.

Изучив код, вы заметите, что у нас есть три компонента React:

Компонент Square отображает одиночную кнопку , а Board отображает 9 квадратов. Компонент Game отображает Board со значениями чисел-заполнителей, которые мы изменим позже. В настоящее время интерактивные компоненты отсутствуют.

Передача данных с помощью props

Для эксперимента, давайте попробуем передать некоторые данные из нашего компонента Board в компонент Square .

В методе renderSquare компонента Board измените код, чтобы передать свойство с именем value в компонент Square :

Измените метод render компонента Square , чтобы он отображал это значение, поменяв на :

После: вы должны увидеть число в каждом квадрате в отрисованном выводе.

Поздравляем! Вы только что «передали свойство» из родительского компонента Board в дочерний компонент Square . Передача свойств — это то, как информация передается от родителей к потомкам в приложениях React.

Создание интерактивного компонента

Давайте заполнять компонент Square значением « X », когда мы щелкаем по нему. Сначала измените тег кнопки, который возвращается из функции render() компонента Square , следующим образом:

Если мы сейчас нажмем на Square, то должны получить предупреждение в нашем браузере.

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

Обратите внимание, что с помощью onClick = <() =>alert (‘click’)> мы передаем функцию в качестве свойства onClick . Она срабатывает только после щелчка. Пропуск () => и запись onClick = — является распространенной ошибкой, которая генерирует предупреждение каждый раз, когда компонент перерисовывается.

Следующим шагом мы хотим, чтобы компонент Square «запомнил», что на него щелкнули, и заполнил себя знаком « X ». Чтобы «запоминать» вещи, компоненты используют состояние.

Компоненты React могут иметь состояние, инициализируя this.state в своих конструкторах. Состояние this.state следует рассматривать как приватное для компонента React, в котором оно определено. Давайте сохраним текущее значение Square в this.state и изменим его при нажатии Square .

Сначала мы добавим конструктор в класс для инициализации состояния:

В классах JavaScript вам всегда нужно вызывать super при определении конструктора подкласса. Все классы компонентов React, имеющие конструктор, должны начинат его с вызова super(props) .

Теперь мы изменим метод render компонента Square для отображения значения текущего состояния при нажатии:

Замените this.props.value на this.state.value внутри тега .

Замените обработчик события () => alert() на () => this.setState() .

Поместите атрибуты className и onClick в отдельные строки для лучшей читаемости.

После этих изменений тег , возвращаемый методом render компонента Square , выглядит следующим образом:

Вызывая this.setState из обработчика onClick в методе render компонента Square , мы говорим React повторно отрисовывать этот Square при каждом нажатии на его кнопку . После обновления свойство this.state.value компонента Square будет иметь значение « X », поэтому мы увидим X на игровом поле. Если вы нажмете на любой квадрат, в нём должен появиться X .

Когда вы вызываете setState в компоненте, React автоматически обновляет и дочерние компоненты внутри него.

Инструменты разработчика

Расширение React Devtools для Chrome и Firefox позволяет вам просматривать дерево компонентов React с помощью инструментов разработчика в вашем браузере.

React DevTools позволяет вам проверять свойства и состояние ваших компонентов React.

После установки React DevTools вы можете щелкнуть правой кнопкой мыши по любому элементу на странице, нажать «Inspect», чтобы открыть инструменты разработчика. Вкладка React появится последней справа.

Однако обратите внимание, что необходимо сделать несколько дополнительных шагов, чтобы заставить его работать с CodePen:

Войдите или зарегистрируйтесь и подтвердите свой адрес электронной почты (необходим для предотвращения спама).

Нажмите кнопку «Fork».

Нажмите «Change View», а затем выберите «Debug mode».

В открывшейся новой вкладке инструменты разработчика теперь должны иметь вкладку React.

Завершение игры

Теперь у нас есть основные строительные блоки для нашей игры в крестики-нолики. Чтобы завершить игру, нам необходимо чередовать размещение « X » и « O » на доске, а также нам нужен способ определить победителя.

Поднятие состояния вверх

В настоящее время каждый компонент Square поддерживает состояние игры. Чтобы определить победителя, мы будем хранить значение каждого из 9 квадратов в одном месте.

Можно предположить, что Board должен просто попросить у каждого Square значение его состояния. Хотя такой подход и возможен в React, мы его не одобряем, потому что код становится сложным для понимания, восприимчивым к ошибкам и трудным для рефакторинга. Вместо этого лучше всего хранить состояние игры в родительском компоненте Board , а не в каждом Square . Компонент Board может указать каждому Square , что отображать, передавая свойство, точно так же, как мы это делали, когда передавали число в каждый Square .

Чтобы собрать данные из нескольких дочерних элементов или обеспечить взаимодействие двумя дочерними компонентами, вам нужно объявить общее состояние в их родительском компоненте. Родительский компонент может передать состояние обратно дочерним компонентам, используя свойства props ; это синхронизирует дочерние компоненты между собой и с родительским компонентом.

Поднятие состояния в родительский компонент является обычным явлением при рефакторинге компонентов React — давайте воспользуемся этой возможностью. Мы добавим конструктор в Board и установим его начальное состояние так, чтобы оно содержало массив с 9 нулями. Эти 9 нулей соответствуют 9 квадратам:

Когда мы позже заполним Board , игровая доска будет выглядеть примерно так:

В настоящее время метод renderSquare в Board выглядит следующим образом:

В начале мы передали свойство value вниз по иерархии компоненту Square из Board , чтобы показывать числа от 0 до 8 в каждом Square . В другом предыдущем шаге мы заменили числа знаком « X », определяемым собственным состоянием Square. Вот почему Square в настоящее время игнорирует свойство value , переданное ему компонентом Board .

Теперь мы снова будем использовать механизм передачи свойств. Мы изменим Board , чтобы проинструктировать каждый отдельный Square о его текущем значении (« X », « O » или null ). У нас уже определен массив squares в конструкторе Board . Давайте изменим метод renderSquare в Board , чтобы читать значения из массива:

Каждый Square теперь получит свойство value , которое будет либо « X »/« O », либо null для пустых квадратов.

Далее нам нужно изменить то, что происходит при нажатии на квадрат. Компонент Board теперь знает, какие квадраты заполнены. Нам нужно создать для Square способ обновить состояние Board . Поскольку состояние считается приватным по отношению к компоненту, который его определяет, мы не можем обновлять состояние Board напрямую из Square .

Чтобы сохранить состояние Board приватным, мы передадим функцию из компонента Board компоненту Square . Эта функция будет вызываться при нажатии на квадрат. Мы изменим метод renderSquare в Board на:

Мастер Йода рекомендует:  Сортировка столбцов в таблице без перезагрузки Javascript

Мы разбиваем возвращаемый элемент на несколько строк для удобства чтения и добавляем скобки, чтобы JavaScript не вставлял точку с запятой после return ломая наш код.

Теперь мы передаем потомкам два свойства из Board в Square : value и onClick . Свойство onClick — это функция, которую Square может вызывать при нажатии. Внесем следующие изменения в Square :

Заменим this.state.value на this.props.value в методе render компонента Square

Заменим this.setState() на this.props.onClick() в методе render компонента Square

Удалим конструктор из Square , потому что он больше не отслеживает состояние игры

После этих изменений компонент Square выглядит следующим образом:

При нажатии на квадрат вызывается функция onClick() , предоставляемая Board . Вот как это достигается:

Свойство onClick() в нативном DOM-компоненте указывает React установить слушатель событий щелчка.

При нажатии на кнопку React вызывает обработчик события onClick() , определенный в методе render() компонента Square .

Этот обработчик событий вызывает this.props.onClick() . Свойство onClick компонента Square было определено компонентом Board .

Так как Board передал onClick = <() =>this.handleClick(i)> в Square , Square при нажатии вызывает this.handleClick(i) .

Мы пока не определили метод handleClick() , поэтому наш код выдает крэш.

Атрибут onClick DOM-элемента имеет особое значение для React, поскольку он является нативным компонентом. Для пользовательских компонентов, таких как Square , наименование зависит от вас. Мы могли бы как угодно назвать метод onClick компонента Square или метод handleClick компонента Board . Однако в React принято использовать имена on[Event] для свойств, которые представляют события, и handle[Event] для методов, которые обрабатывают события.

Когда мы попытаемся кликнуть по квадрату, мы должны получить ошибку, потому что мы еще не определили handleClick . Теперь мы добавим handleClick в класс Board:

После этих изменений мы снова можем нажимать на квадраты, чтобы заполнить их. Однако теперь состояние хранится в компоненте Board вместо отдельных компонентов Square . При изменении состояния Board компоненты Square автоматически перерисовываются. Хранение состояния всех квадратов в компоненте Board в будущем позволит определить победителя.

Поскольку компоненты Square больше не поддерживают состояние, они получают значения от компонента Board и информируют компонент Board при клике по ним. В терминах React-компоненты Square теперь являются контролируемыми компонентами. Board их полностью контролирует.

Обратите внимание, что в handleClick мы вызываем .slice() , чтобы создать копию массива квадратов для его изменения вместо изменения существующего массива. Мы объясним, почему мы создаем копию массива квадратов в следующей главе.

Почему важна неизменяемость

В предыдущем примере кода мы предложили использовать оператор .slice() , чтобы создать копию массива квадратов для изменения вместо изменения существующего массива. Теперь мы обсудим неизменяемость и то, почему важно её изучить.

Как правило, существует два подхода к изменению данных. Первый подход заключается в мутировании данных путем прямого изменения значений. Второй подход заключается в замене данных новой копией, которая имеет желаемые изменения.

Изменение данных с помощью мутации

Изменение данных без мутации

Конечный результат такой же, но не изменяя (или не изменяя оригинальные данные) напрямую, мы получаем несколько преимуществ, описанных ниже.

Сложные функции становятся простыми

Неизменяемость делает сложные функции намного проще в реализации. Позже в этом учебнике мы реализуем функцию «путешествие во времени», которая позволяет нам просматривать историю игры в крестики-нолики и «перепрыгивать» к предыдущим ходам. Такая функциональность не является специфичной для игр — способность отменять и повторять определенные действия является распространенным требованием в приложениях. Избежание прямой мутации данных позволяет нам сохранить предыдущие версии истории игры нетронутыми и использовать их позже.

Отслеживание изменений

Обнаружить изменения в мутируемых (изменяемых) объектах сложно, потому что они изменяются напрямую. Такое обнаружение требует, чтобы изменяемый объект сравнивался с предыдущими копиями самого себя и всего дерева объектов перемещения.

Обнаружение изменений в неизменяемых объектах значительно проще. Если неизменяемый объект, на который ссылаются, отличается от предыдущего, то объект изменился.

Определение момента, когда необходима перерисовка в React

Основным преимуществом неизменяемости является то, что она помогает создавать чистые компоненты в React. Неизменяемые данные могут легко определить, были ли внесены изменения, что в свою очередь помогает определить, когда компонент требует повторной отрисовки.

Вы можете узнать больше о shouldComponentUpdate() и о том, как создавать чистые компоненты, прочитав раздел «Оптимизация производительности».

Компоненты-функции

Теперь мы изменим Square на компонент-функцию.

В React компоненты-функции являются более простым способом написания компонентов, которые содержат только метод отрисовки и не имеют своего собственного состояния. Вместо определения класса, который расширяет React.Component , мы можем написать функцию, которая принимает свойства props в качестве входных данных и возвращает то, что должно быть отображено. Компоненты-функции пишутся менее утомительно, чем классы, и многие компоненты могут быть выражены именно таким образом.

Заменим класс Square такой функцией:


Мы изменили this.props на props в обоих местах, где он встречается.

Когда мы выразили Square как компонент-функцию, мы также изменили onClick= <() =>this.props.onClick()> на более короткий onClick= (обратите внимание на отсутствие скобок с обеих сторон). В классе мы использовали стрелочную функцию для доступа к правильному значению this , но в компоненте функции нам не нужно об этом беспокоиться.

По очереди

Теперь нам нужно исправить очевидный дефект в нашей игре в крестики-нолики: буквы «O» не могут быть отмечены на доске.

Мы установим первый ход в «X» по умолчанию. Мы можем установить это значение по умолчанию, изменив начальное состояние в нашем конструкторе Board :

Каждый раз, когда игрок делает ход, xIsNext (логическое значение) будет инвертирован, чтобы определить, какой игрок пойдет дальше, и состояние игры будет сохранено. Мы обновим функцию handleClick в Board , чтобы инвертировать значение xIsNext :

С этим изменением «Х» и «О» могут сменяться. Давайте также изменим текст переменной status в методе render компонента Board , чтобы он отображал, какой игрок должен ходить следующим:

После применения этих изменений у вас должен получиться такой компонент Board:

Объявление победителя

Теперь, когда мы показываем, какой игрок ходит следующим, мы также должны показать ситуацию, когда игра выиграна, и ходов больше нет. Мы можем определить победителя, добавив эту вспомогательную функцию в конец файла:

Мы будем вызывать calculateWinner(squares) в методе render компонента Board , чтобы проверить, выиграл ли игрок. Если игрок выиграл, мы можем отобразить текст, такой как «Победитель: X» или «Победитель: O». Заменим объявление переменной status в методе render компонента Board следующим кодом:

Теперь мы можем изменить функцию handleClick в Board , чтобы выполнять return раньше, игнорируя клик, если кто-то выиграл игру или Square уже заполнен:

Поздравляем! Теперь у вас есть рабочая игра в крестики-нолики. Также вы только что изучили основы React, являясь, возможно, настоящим победителем.

Добавление путешествия во времени

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

Хранение истории ходов

Если бы мы мутировали массив squares , реализация путешествия во времени была бы очень сложной.

Однако мы использовали slice() для создания новой копии массива squares после каждого перемещения и рассматривали его как неизменяемый. Теперь это позволит нам сохранять каждую прошлую версию массива squares и перемещаться между ходами, которые уже произошли.

Мы будем хранить прошлые массивы squares в другом массиве, называемом history . Массив history представляет все состояния Board , от первого до последнего хода, и имеет следующую форму:

Теперь нам нужно решить, какой компонент должен владеть состоянием history .

Очередное поднятие состояния

Мы хотим, чтобы компонент Game верхнего уровня отображал список прошлых ходов. Для этого ему понадобится доступ к history , поэтому мы поместим состояние history в компонент Game верхнего уровня.

Помещение состояния history в компонент Game позволяет нам удалить состояние squares из его дочернего компонента Board . Подобно тому, как мы «подняли состояние» из компонента Square в компонент Board , теперь мы поднимаем его из Board в компонент Game верхнего уровня. Это дает компоненту Game полный контроль над данными Board и позволяет ему инструктировать Board отрисовывать предыдущие ходы из history .

Во-первых, мы установим начальное состояние для компонента Game в его конструкторе:

Далее у нас будет компонент Board , получающий свойства squares и onClick из компонента Game . Так как теперь у нас есть единый обработчик кликов в Board для всех Square , нам нужно будет передавать местоположение каждого Square в обработчик onClick , чтобы указать, на какой квадрат кликнули. Вот необходимые шаги для преобразования компонента Board :

Удалить конструктор в Board.

Заменить this.state.squares[i] на this.props.squares[i] в методе renderSquare компонента Board .

Заменить this.handleClick(i) на this.props.onClick(i) в методе renderSquare компонента Board .

Компонент Board теперь выглядит так:

Обновим функцию render компонента Game , чтобы использовать самую последнюю запись в истории для определения и отображения статуса игры:

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

Наконец, нам нужно переместить метод handleClick из компонента Board в компонент Game . Нам также нужно изменить handleClick , поскольку состояние компонента Game структурировано по-другому. В методе handleClick компонента Game мы объединяем новые записи истории в history .

В отличие от метода push() массива, с которым вы, возможно, более знакомы, метод concat() не изменяет исходный массив, поэтому мы предпочитаем его.

На данный момент компонент Board нуждается только в методах renderSquare и render . Состояние игры и метод handleClick должны находиться в компоненте Game .

Показ предыдущих ходов

Поскольку мы записываем историю игры в крестики-нолики, теперь мы можем отобразить ее игроку в виде списка прошлых ходов.

Ранее мы узнали, что элементы React являются первоклассными объектами JavaScript; мы можем передавать их в наших приложениях. Чтобы отрисовывать несколько элементов в React, мы можем использовать массив React элементов.

В JavaScript у массивов есть метод map() , который обычно используется для отображения данных на другие данные, например:

Используя метод map , мы можем сопоставить нашу историю ходов с элементами React, представляющими кнопки на экране, и отобразить список кнопок, чтобы «перейти» к прошлым ходам.

Давайте сопоставим историю в методе render компонента Game :

Для каждого хода в истории игры в крестики-нолики мы создаем элемент списка
, который содержит кнопку . Эта кнопка имеет обработчик onClick , который вызывает метод this.jumpTo() . Мы еще не реализовали метод jumpTo() . Пока что мы должны увидеть список ходов, которые произошли в игре, и предупреждение в консоли инструментов разработчика, которое гласит:

Each child in an array or iterator should have a unique “key” prop. Check the render method of “Game”.

Каждый дочерний элемент в массиве или итераторе должен иметь уникальное свойство » key «. Проверьте метод render компонента Game .

Давайте обсудим, что означает приведенное выше предупреждение.

Выбор ключа

Когда мы отображаем список, React хранит некоторую информацию о каждом отображаемом элементе списка. Когда мы обновляем список, React должен определить, что изменилось. Мы могли бы добавлять, удалять, переупорядочивать или обновлять элементы списка.

Представьте себе переход от

В дополнение к обновленным счетчикам, человек, читающий это, вероятно, сказал бы, что мы поменяли местами Петю и Васю и вставили между ними Лёню. Однако React — это компьютерная программа, которая не знает наших намерений. Поскольку это так, нам необходимо указать свойство key для каждого элемента списка, чтобы отличать его соседних элементов в этом списке. Один из вариантов — использовать строки vasia , petia , lyonia . Если бы мы отображали данные из базы данных, в качестве ключей могли бы использоваться идентификаторы (поле id) базы данных для Васи, Пети и Лёни.

При повторной отрисовке списка React берет ключ каждого элемента списка и ищет соответствующие элементы в предыдущем списке. Если в текущем списке есть ключ, которого раньше не было, React создает компонент. Если в текущем списке отсутствует ключ, который существовал в предыдущем списке, React уничтожает предыдущий компонент. Если два ключа совпадают, соответствующий компонент перемещается. Ключи сообщают React об идентичности каждого компонента, что позволяет React поддерживать состояние между повторными отрисовками. Если ключ компонента изменится, он будет уничтожен и воссоздан с новым состоянием.

Ключ — это специальное и зарезервированное свойство в React (наряду с ref , более продвинутой функцией). Когда элемент создан, React извлекает свойство key и сохраняет его непосредственно в возвращаемом элементе. Даже если key может выглядеть так, как будто он принадлежит props , на него нельзя ссылаться, используя this.props.key . React автоматически использует key , чтобы решить, какие компоненты обновлять. Компонент не может узнать о своем ключе key .

Настоятельно рекомендуется назначать правильные ключи key при создании динамических списков. Если у вас нет подходящего ключа key , вы можете подумать о реструктуризации ваших данных.

Если ключ не указан, React выдаст предупреждение и по умолчанию будет использовать индекс массива в качестве ключа. Использование индекса массива в качестве ключа вызывает проблемы при попытке изменить порядок или при вставке/удалении элементов списка. Явная передача key= отключает предупреждение, но имеет те же проблемы, что и индексы массивов, и в большинстве случаев не рекомендуется.

Ключи не должны быть глобально уникальными; они должны быть уникальными только между компонентами и их соседями. То есть уникальными только в пределах данного списка. В другом, к примеру соседнем списке, значения ключей могут совпадать со значениями текущего списка, но это никак не влияет на его работу, так как эти два подмножества ключей рассматриваются React полностью независимо, то есть они друг о друге не знают.

Реализация путешествия во времени

В истории игры в крестики-нолики каждый предыдущий ход имеет свой уникальный идентификатор — это порядковый номер хода. Ходы никогда не переупорядочиваются, не удаляются и не вставляются в середину, поэтому здесь безопасно использовать индекс хода в качестве ключа.

В методе render компонента Game мы можем добавить ключ как
, и предупреждение React о ключах должно исчезнуть:

Нажатие любую из кнопок элемента списка приводит к ошибке, потому что метод jumpTo не определен. Прежде чем мы перейдем к реализации jumpTo , добавим stepNumber в состояние компонента Game , чтобы указать, какой шаг мы сейчас просматриваем.

Сначала добавим stepNumber: 0 в начальное состояние в конструкторе Game :

Далее мы определим метод jumpTo в Game , чтобы обновлять stepNumber . Мы также устанавливаем xIsNext в true , если число, на которое мы меняем stepNumber , является четным:

Теперь мы внесем несколько изменений в метод handleClick комопнента Game , который срабатывает при нажатии на квадрат.

Добавленное нами состояние stepNumber отражает текущий ход, отображаемый для пользователя. После того, как мы сделаем новый шаг, нам нужно обновить stepNumber , добавив stepNumber: history.length в качестве аргумента this.setState . Это гарантирует, что мы не застрянем, показывая тот же самый ход после того, как был сделан новый.

Мы также заменим чтение this.state.history на this.state.history.slice(0, this.state.stepNumber + 1) . Это гарантирует, что если мы «вернемся назад во времени», а затем сделаем новый шаг с этой точки, мы затрем всю «будущую» историю, которая теперь стала бы неверной.

Наконец, мы изменим метод render компонента Game , на данный момент всегда отрисовывающий последний ход, чтобы он отрисовывал текущий выбранный ход в соответствии со stepNumber :

Если мы нажмем на какой-либо шаг в истории, игровое поле должно немедленно обновиться, чтобы показать, как оно выглядело после того, как этот шаг произошел.

Подведение итогов

Поздравляем! Вы создали игру в крестики-нолики, которая:

позволяет вам играть в крестики-нолики,

показывает, когда игрок выиграл,

хранит историю игры,

позволяет игрокам просматривать как историю игры, так и предыдущие версии игрового поля.

Отличная работа! Мы надеемся, что теперь вы почувствовали, что хорошо понимаете, как работает React.

Проверьте окончательный результат здесь: Окончательный результат

Если у вас есть дополнительное время или вы хотите попрактиковаться в новых навыках React, вот несколько идей по улучшению, которые вы можете добавить в игру в крестики-нолики, перечисленные в порядке возрастания сложности:

Отображение местоположения для каждого хода в формате (столбец, строка) в списке истории ходов.

Выделите текущий выбранный элемент в списке ходов.

Перепишите компонент Board , чтобы использовать два цикла для создания квадратов вместо их жесткого кодирования.

Добавьте кнопку-переключатель, которая позволяет сортировать ходы в порядке возрастания или убывания.

Когда кто-то выигрывает, выделите три квадрата, которые привели к победе.

Когда никто не выигрывает, выведите сообщение о ничье.

Создание собственной библиотеки валидации на React: дополнительные функции (часть 2) Javascript

Частная коллекция качественных материалов для тех, кто делает сайты

  • Фотошоп-мастер2000+ уроков по фотошопу
  • Фото-монстр300+ уроков для фотографов
  • Видео-смайл200+ уроков по видеообработке
  • Жизнь в стиле «Кайдзен» Техники и приемы для гармоничной и сбалансированной жизни
  • Главная»
  • Уроки»
  • Уроки jQuery для начинающих

В этой рубрике Вы найдете уроки по Javascript библиотеке jQuery.

Анимация набора текста на jQuery

Сегодня мы бы хотели вам рассказать о библиотеке TypeIt — бесплатном jQuery плагине. С её помощью можно имитировать набор текста. Если всё настроить правильно, то можно добиться очень реалистичного эффекта.

Временная шкала на jQuery

jQuery плагин для создания временной шкалы.

Заметка: Перезагрузка и редирект на JavaScript

Быстрая заметка, где вы сможете найти парочку JS сниппетов для перезагрузки и перенаправления пользователей через JavaScript.

Рисуем диаграмму Ганта

jQuery плагин для создания диаграммы Ганта.

AJAX и PHP: загрузка файла

Пример того как осуществить загрузку файла через PHP и jQuery ajax.

Stimed — стили в зависимости от времени суток

Интересная библиотека с помощью которой можно задать определённым элементам страницы особые стили в зависимости от времени суток.

jQuery плагин для отображения превью загружаемого файла

Небольшой jQuery плагин, который позволит увидеть миниатюру изображения ещё до загрузки на сервер.

Функциональное программирование с примерами на JavaScript. Часть вторая. Аппликативные функторы, curryN и валидации

В прошлой части мы рассмотрели основные инструменты функционального программирования с примерами на JavaScript: монады, функторы, каррирование. В этой статье мы закончим обзор принципов и инструментов, которые помогут вам построить поистине чистое приложение в функциональном стиле.

Пример 3. Задание значений объектам, которые могут равняться Null

Используемые концепты ФП: Аппликативные функторы.

Сценарий использования: Предположим, что мы хотим предоставить скидку пользователю, если пользователь залогинен и у нас есть действующее предложение (т.е. существует скидка).

Для этой задачи мы будем использовать метод applyDiscount, представленный ниже. Этот метод может выбрасывать ошибки типа null в случае, если пользователь или скидка равняется null.

Давайте посмотрим, как мы можем решить эту задачу, используя аппликативные функторы.

Аппликативный функтор

Любой класс, у которого есть метод ap и который имплементирует спецификацию Applicative, называется аппликативным функтором. Аппликативные функторы используются в функциях, которые работают с возможными null-значениями в правой и левой части присваивания.

Оказывается, Maybe-монады также реализуют метод ap, и, следовательно, являются аппликативными функторами. Таким образом, мы можем использовать Maybe-монады для решения этой задачи.

Давайте взглянем на то, как заставить функцию applyDiscount работать, используя Maybe-монады в качестве аппликативных функторов.

Шаг 1: Обернем потенциальные null-объекты в Maybe-монады.

Шаг 2: Перепишем функцию так, чтобы она могла принимать один параметр за раз (каррируем её).

Шаг 3: Передадим первый агрумент (maybeUser) в метод applyDiscount, используя map.

Шаг 4: Используем maybeApplyDiscountFunc.

XYZ school, Москва, до 250 000 ₽

Значение maybeApplyDiscountFunc может быть:

  1. функцией, обернутой в Maybe, если пользователь существует.
  2. Nothing, если пользователь равен null.

Если пользователь равен null, то при передаче второго аргумента в функцию, ничего не произойдет. Не выбросятся также и ошибки, связанные с нулевыми значениями.

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

Мы столкнулись с проблемой: map не знает, как запустить функцию, когда она обернута в Maybe-монаду.

В этом случае нам нужен другой метод, который умеет работать с обернутыми функциями. На помощь нам приходит метод ap.

Шаг 5: Используем функцию ap. Этот метод принимает монаду Maybe и выполняет функцию, хранящуюся внутри.

Применим метод ap:

Подведем итог: если у вас есть функция, которая работает с несколькими переменными, значения которых может быть null, вы должны сначала каррировать её, а затем обернуть в Maybe. Кроме этого, поместите все параметры в Maybe и используйте ap, чтобы запустить функцию.

Множественное каррирование

Мы уже познакомились с каррированием в прошлой части цикла. Оно позволяет передавать значения в функцию, которая принимает несколько аргументов, по одному.

Но что если у нас будет функция, которая может суммировать не два, а несколько аргументов?

Мы все еще можем каррировать эту функцию, ограничивая число аргументов, используя curryN:

Использование curryN для ожидания определенного количества вызовов функции.

Предположим, что мы хотим реализовать функцию, которая выводит лог только после 3х её вызовов.

Мы можем написать эту функцию в функциональном стиле, используя curryN:

Пример 4. Сбор и отображение нескольких ошибок

Освещенные темы: Валидации (Валидационный функтор, Валидационный аппликативный функтор, Валидационная монада)

Валидации подобны монадам Either и используются в работе с композицией функций, выбрасывающих ошибки. Но, в отличие от Either, в котором для композиции используется метод chain, в валидационных монадах мы обычно используем метод ap. Также, в отличие от метода chain, который позволяет отобразить только первую ошибку, метод ap позволяет собрать массив из всех исключений.

Они обычно используются в валидациях форм, в которых все ошибки, возникшие при заполнении, показываются сразу же.

Сценарий использования: У нас есть форма регистрации, в которой валидируются имя пользователя, пароль и e-mail с помощью трех функций: isUsernameValid, isPwdLengthCorrect и isEmailValid. Мы должны показать одну, две или три ошибки в зависимости от введенных данных.

Давайте реализуем эту задачу, используя валидационный аппликативный функтор.

Мы будем использовать библиотеку data.validation из folktalejs, поскольку в ramda-fantasy еще не реализованы валидации.

У валидационного функтора есть два конструктора: Success и Failure, по аналогии с монадой Either.

Шаг 1: Чтобы использовать валидации, все, что нам нужно сделать — обернуть валидные значения и ошибки в Success и Failure.

Проделайте это для всех полей формы.

Шаг 2: Создайте функцию-заглушку.

Шаг 3: Используйте curryN, чтобы повторно применить ap.

Проблема с функцией ap в том, что левая часть выражения должна быть функтором или монадой, содержащей функцию.

Мастер Йода рекомендует:  Руководство по борьбе со стрессом для программистов

Например, предположим, что мы хотим повторно применить ap, как показано ниже. Это будет работать только в том случае, когда monad1 содержит функцию. Результат monad1.ap(monad2) также должен быть монадой, содержащей функцию, чтобы мы могли использовать ap на monad3.

В нашем случае у нас есть 3 функции, которые нам надо применить

Давайте предположим, что мы сделали что-то вроде:

Код выше не сработает, потому что Success(returnSuccess).ap(isUsernameValid(username)) вернет значение, и мы не сможем вызвать от него метод ap.

Мы можем использовать curryN, чтобы возвращать функцию, пока она не вызвана N раз.

Основные библиотеки и фреймворки JavaScript, которые вы должны знать

JavaScript существует уже более 20 лет, и это один из тех языков, которые никогда не перестают развиваться. В последнее время язык быстро развивается, что заставляет меня задаться вопросом, будут ли современные технологии JavaScript для начинающих, которые хорошо известны сегодня, актуальными через пару лет.

Тем не менее, важно быть впереди, работая с новейшими инструментами и фреймворками для улучшения рабочего процесса разработки. В этой статье рассматриваются различные библиотеки JavaScript, фреймворки и инструменты, которые вы должны изучать прямо сейчас.

Введение

Среда JavaScript стала огромной. Она имеет собственную экосистему библиотек, фреймворков, инструментов, менеджеров пакетов и новых языков, которые компилируются в JavaScript. Интересно, что npm, который является де-факто-менеджером пакетов для JavaScript, также является крупнейшим в мире реестром программного обеспечения. Вот выдержка из публикации, опубликованной на Linux.com еще в январе 2020 года.

В более чем 350 000 пакетов содержит реестр npm, что более чем вдвое больше, чем следующий наиболее популярный реестр пакетов (который является репозиторием Apache Maven). Фактически, в настоящее время это самый крупный реестр пакетов в мире.

Перенеситесь вперед на восемь месяцев, и в настоящее время в реестре npm есть около 500 000 пакетов. Это огромный рост по сравнению с другими репозиториями пакетов.

Будучи разработчиком JavaScript на начальном этапе, важно не отставать от современных инструментов и библиотек JavaScript. Когда технология становится популярной, спрос на нее высок, что, в свою очередь, означает больше заданий по написани кода, где платят самую высокую зарплату в отрасли. Поэтому я собрал список популярных технологий JavaScript, которые, как я думаю, вам следует знать.

Библиотеки

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

Вы можете вызвать библиотечную функцию и передать ей некоторые параметры, и библиотека выполнит ее и вернет вам элемент управления. Тем не менее, это не создает каких-либо структурных ограничений, которые ограничивают использование библиотеки. Популярные библиотеки JavaScript включают:

React

React — это библиотека JavaScript, созданная разработчиками Facebook и Instagram. Согласно опросу Stack Overflow Survey 2020, React был признан самой популярной технологией среди разработчиков. React также имеет честь быть самым популярным проектом JavaScript, согласно количеству звезд на GitHub.

Так почему React получает все внимание? С помощью React можно создать интерактивный интерфейс с использованием декларативного подхода, в котором вы можете контролировать состояние приложения, говоря: «Представление должно выглядеть так». Он использует компонентную модель, в которой компоненты являются повторно используемыми элементами пользовательского интерфейса, и каждый компонент имеет свое собственное состояние.

React использует виртуальную модель DOM, так что вам не нужно беспокоиться о прямом манипулировании с DOM. Другие примечательные особенности React включают однонаправленный поток данных, дополнительный синтаксис JSX и инструмент командной строки для создания проекта React с нуля.

Если вы считаете, что «React» — это лучшая вещь, и вы хотели бы изучить « React», ознакомьтесь с нашей учебной серией «React Crash Course for Beginners».

JQuery

jQuery — это библиотека, которая сделала JavaScript более доступным а DOM-манипуляцией проще, чем раньше. Плавная кривая обучения jQuery и простой синтаксис породили на стороне клиента новое поколение новых разработчиков. Несколько лет назад jQuery считался прочным решением для создания надежных веб-сайтов с поддержкой кросс-браузерности. Основные функции jQuery, такие как манипулирование DOM на основе селекторов CSS, обработка событий и создание вызовов AJAX, подпитывали его популярность.

Однако все изменилось, и среда JavaScript постоянно развивается. Некоторые функции jQuery были включены в новую спецификацию ECMAScript. Более того, новые библиотеки и фреймворки, используемые сегодня, имеют собственный способ связывания DOM, и поэтому простые методы манипуляции с DOM больше не требуются. Популярность jQuery находится на спаде, но я не вижу, чтобы эта библиотека исчезла в ближайшее время.

D3: Документы, управляемые данными

D3 (или D3.js) — мощная библиотека JavaScript для создания интерактивных визуализаций с использованием веб-стандартов, таких как SVG, HTML и CSS. В отличие от других библиотек визуализации, D3 предлагает лучший контроль над окончательным визуальным результатом.

D3 работает, связывая данные с DOM и затем преобразуя их в документ. Она также имеет собственную экосистему, которая состоит из плагинов и библиотек, которые расширяют ее базовые функциональные возможности. Библиотека существует с 2011 года, и в ней есть множество документации и учебников, которые помогут вам начать работу.

Если вы хотите создать простые визуализации, не вкладывая слишком много времени в это, вы должны обратить внимание на Chart.js. У нас есть вводная серия про Chart.js, которая охватывает большинство визуализаций, которые вы можете создать с помощью Chart.js

Фреймворки

Фреймворк имеет архитектуру, которая диктует поток управления в вашем приложении. Фреймворк описывает скелет и рассказывает вам, как все должно быть организовано. Вам также предоставляются основные функции, необходимые для запуска вашего приложения. Кроме того, вы обязаны следовать принципам и шаблонам фреймворка. Разница между фреймворком и библиотекой заключается в том, что вы вызываете библиотеку, тогда как фреймворк вызывает вас.

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

Angular


AngularJS когда-то была самой популярной технологией JavaScript среди разработчиков интерфейсов. Он был поддержан Google и сообществом частных лиц и корпораций. Несмотря на популярность, у AngularJS была своя доля недостатков. Команда Angular провела два года работы над новой версией Angular, которая была наконец выпущена в сентябре 2020 года.

Выпуск Angular 2 был переделкой AngularJS. Некоторые из функций Angular 2 включают:

  • TypeScript над JavaScript как язык по умолчанию
  • компонентная архитектура
  • улучшенная производительность как на мобильных, так и на веб-платформах.
  • лучшие инструменты и варианты исходных каркасов

Тем не менее, модернизация от Angular 1.x до Angular 2 является дорогостоящей, потому что Angular 2 — совершенно другой зверь. Это одна из причин, почему Angular 2 не был так сразу же принят, как свой предшественник. Но Angular и AngularJS по-прежнему относятся к числу наиболее часто используемых технологий в соответствии со Stack Overflow (2020). Проект Angular имеет около 28 000 звезд в GitHub.

Vue.js

Vue.js — это легкий JavaScript фреймворк, который активно развивается в этом году. Это самый популярный JavaScript фреймворк на GitHub с точки зрения звезд GitHub. Vue утверждает, что это менее упрямый фреймворк и, таким образом более удобный в использовании. Синтаксис шаблона на основе HTML Vue связывает отрисовываемый DOM с данными экземпляра.

Фреймворк предлагает опыт, похожий на React, с его виртуальными DOM и компонентами повторного использования, которые можно использовать для создания как виджетов, так и целых веб-приложений. Кроме того, вы также можете использовать синтаксис JSX для непосредственного написания функций рендеринга. Когда состояние изменяется, Vue.js использует систему реактивности, чтобы определить, что изменилось и перерисовывает минимальное количество компонентов. Vue.js также поддерживает интеграцию других библиотек во фреймворк без особых хлопот.

Ember.js

Ember.js является фронт-енд фреймворком на основе шаблона Model-View-ViewModel (MVVM). Фреймворк использует стандартный подход к конфигурации, который популярен среди серверных фреймворков таких как Ruby on Rails и Laravel. Ember.js включает в себя общие идиомы и лучшие практики фреймворков, чтобы вы могли получать приложение без особых усилий.

Стек Ember обычно включает:

  • Ember CLI: предоставляет основные варианты каркаса приложения и поддерживает сотни надстроек.
  • Ember Data: библиотека сохранения данных, которая может быть настроена для работы с любым сервером.
  • Ember Inspector: расширение доступное для Chrome и Firefox.
  • Liquid Fire: дополнение для переходов и анимаций.

Инструменты

Инструмент представляет собой набор подпрограмм, которые помогут вам в процессе разработки. В отличие от библиотеки, инструмент обычно выполняет задачу над клиентским кодом. Он берет ваш код в качестве входных данных, выполняет на нем задачу, а затем возвращает результат. Обычно используемые инструменты включают в себя транспайлеры и инструменты для сборки, сборщики ресурсов и другие.

Инструменты: выполнение общих задач

Инструменты, выполняющие общие задачки — это инструменты, используемые для автоматизации определенных повторяющихся задач. В число самых популярных входят:

Gulp — это набор инструментов JavaScript, который используется как менеджер задач и как система сборки в веб-разработке. Компиляция, минимизация кода, оптимизация изображений, модульное тестирование, линтинг и т.д. — это повторяющиеся задачи, которые должны быть автоматизированы. Gulp упрощает процесс написания задач даже для людей, которые менее знакомы с JavaScript.

Gulp использует конвейеры для потоковой передачи данных из одного плагина в другой, и конечный результат выводится в папку назначения. Gulp работает лучше по сравнению с Grunt, потому что он не создает временные файлы для хранения промежуточных результатов, что приводит к меньшему количеству вызовов ввода-вывода.

Grunt

Grunt — это менеджер задач и инструмент автоматизации JavaScript. Grunt имеет интерфейс командной строки, который позволяет запускать настраиваемые задачи, определенные в файле, называемом Gruntfile. У Grunt есть тысячи плагинов на выбор, которые должны охватывать большинство обычных повторяющихся задач, с которыми вы столкнулись. С помощью Grunt вы можете запускать все задачи под одной командой, что упрощает вашу жизнь.

Gulp и Grunt требуют, чтобы вы потратили время на изучение и освоение нового инструмента, что требует времени. Ввод дополнительных зависимостей в ваш проект можно избежать, выбирая альтернативу, которая уже связана с Node.js. Хотя npm более известен как менеджер пакетов, сценарии npm можно использовать для выполнения основной части вышеупомянутых задач.

Инструменты: тестирование

Тестирование — это процесс проверки и валидации того, что приложение соответствует ожидаемым бизнес и техническим требованиям. Подход, основанный на тестах, также помогает обнаруживать ошибки и, следовательно, его следует рассматривать как неотъемлемую часть современного процесса разработки.

Jest — это относительно новый фреймворк для тестирования, созданный в Facebook и хорошо принятый сообществом React. Существует распространенное заблуждение, что Jest специально разработан для работы с React; однако, согласно документации Jest:

Несмотря на то, что Jest можно рассматривать как фреймворк тестирования специфичный для React, на самом деле это универсальная платформа тестирования, способная адаптироваться к любой библиотеке или фреймворку JavaScript. Вы можете использовать Jest для тестирования любого кода JavaScript.

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

Jest имеет функцию под названием snapshot testing, которая позволяет гарантировать, что пользовательский интерфейс приложения неожиданно не изменится. Разработчики в Facebook и другие участники недавно вложили много работы в этот проект, поэтому не удивительно, что Jest окажется самой популярной тестовой платформой для JavaScript в ближайшие годы.

Mocha

Mocha — это фреймворк для тестирования JavaScript, который предоставляет поддержку браузера, асинхронные вызовы, включая обещания, отчеты о тестовом покрытии и JavaScript API для запуска тестов. Mocha часто используется с библиотекой утверждений, такой как Chai, should.js, expect.js или better-assert, потому что у нее нет собственной библиотеки утверждений.

Jasmine

Jasmine — это фреймворк для тестирования JavaScript, ориентированный на поведение. Jasmine стремится стать браузером, платформой и независимым от платформы набором тестов. У Jasmine есть своя собственная библиотека утверждений, называемая matchers, которая дает ему чистый и легко читаемый синтаксис. Jasmine не имеет встроенной команды для выполнения тестов, и вам, возможно, придется использовать какую-нибудь общую, например, Karma.

Резюме

JavaScript, язык Интернета, остался актуальным со времен его создания еще в 1995 году. Вероятно, он останется таким же, пока браузеры не решат отказаться от него в пользу какого-нибудь другого языка. Несмотря на то, что существует множество других языков, которые скомпилируются с использованием JavaScript, нет другого языка сценариев, который заменит JavaScript в обозримом будущем. Почему? Потому что JavaScript стал слишком популярным, чтобы его можно было заменить.

Язык не лишен кривых обучения, и есть множество фреймворков и библиотек, которые смогут вас занять. Если вы ищете дополнительные ресурсы для изучения или использования в своей работе, ознакомьтесь с тем, что у нас есть на рынке Envato.

Среда JavaScript определенно развивается, что видно из текущих тенденций в веб-разработке. Старые библиотеки и фреймворки были заменены новыми технологиями. jQuery, которая когда-то была наиболее популярной библиотекой JavaScript, испытывает спад с точки зрения привлекательности, использования и популярности. Новое поколение фронт-енд библиотек, фреймворков и инструментов набирает силу и получает всеобщее признание.

Привыкание к новым тенденциям в технологии также имеет свои преимущества. Задачи по написанию кода, требующие знания React, имеют одни из самых высоких зарплат в отрасли со средней зарплатой в размере 105 000 долларов США в соответствии с Stack Overflow (2020). Поэтому вам нужно продолжить обучение и экспериментировать с новейшими инструментами и фреймворками, чтобы максимально использовать JavaScript.

Если вы считаете, что я пропустил фреймворк JavaScript, библиотеку или инструмент, о которых стоит упомянуть, дайте мне знать в комментариях.

Создание форм с помощью React – все что нужно знать

Дата публикации: 2020-06-14

От автора: формы являются неотъемлемой частью любого современного приложения. Они служат основным средством взаимодействия пользователей с вашим приложением. Разработчики полагаются на формы для всего: безопасный вход в систему пользователя, поиск и фильтрация списка продуктов, бронирование продукта и построение корзины и т. Д. Более сложные приложения, созданные для предприятий, обычно более интенсивно заполняются, при этом поля ввода охватывают несколько вкладок. Кроме того, нужно учесть и развернуть логику проверки.

В этом уроке мы рассмотрим, как обрабатывает React формы. Мы рассмотрим не только основы, но также сформируем валидацию и передовые методы — даже опытные разработчики неправильно понимают определенные детали.

Создание формы — контролируемый или неконтролируемый компонент

React предлагает устойчивый, реактивный подход к созданию форм. В отличие от других элементов DOM, HTML элементы формы работают по-разному в React. Данные формы, например, обычно обрабатываются компонентом, а не DOM, и обычно реализуются с использованием контролируемых компонентов. На изображении ниже прекрасно описывается, как контролируемые компоненты работают в React.

Структура формы аналогична структуре обычных HTML-форм. Однако каждый элемент ввода получает свой собственный компонент, который мы называем немым компонентом. Контейнерный компонент отвечает за поддержание состояния. Разница заключается в том, что мы используем функцию обратного вызова для обработки событий формы, а затем с использованием состояния контейнера для хранения данных формы. Это дает вашему компоненту лучший контроль над элементами управления формой и данными формы.

Как создать сайт самому?

Какие технологии и знания необходимы сегодня, чтобы создавать сайты самостоятельно? Узнайте на интенсиве!

Функция обратного вызова активируется на событиях, включая изменение значений управления формой или при отправке формы. Затем функция подталкивает значения формы в локальное состояние компонента, а затем данные управляются компонентом. Поскольку мы используем атрибут value в элементе формы, отображаемое значение будет значением this.state.value.

Существует еще один метод, известный как неконтролируемые компоненты, для создания входных форм. Это больше похоже на традиционные HTML-формы, поскольку данные входной формы хранятся внутри DOM, а не внутри компонента. Элементы типа input и textarea сохраняют свое собственное состояние, которое они обновляют при изменении входных значений. Вы можете запросить DOM значения поля ввода с помощью ссылки.

Вот пример из официальной документации, демонстрирующий работу неконтролируемых компонентов.

Основные библиотеки, инструменты и фреймворки JavaScript, которые вы должны знать

JavaScript существует уже более 20 лет, и это один из тех языков, который не перестает развиваться. Язык переживал быстрый рост в последнее время, что заставляет задуматься, будут ли современные интерфейсные технологии JavaScript, которые хорошо известны сегодня, актуальны через пару лет.

Тем не менее, важно играть на опережение, работая с новейшими инструментами и фреймворками для улучшения процесса разработки. В этой статье рассматриваются различные библиотеки JavaScript, фреймворки и инструменты, которые вам следует рассмотреть для изучения прямо сейчас.

Введение

Среда JavaScript стала просто огромной. Она имеет собственную экосистему библиотек, фреймворков, инструментов, менеджеров пакетов и новых языков, которые компилируются до JavaScript. Интересно, что NPM, который является де-факто менеджером пакетов для JavaScript, также является крупнейшим в мире реестром программного обеспечения. Вот выдержка из публикации, опубликованной на Linux.com еще в январе 2020 года.

С более чем 350 000 пакетами, реестр NPM содержит более чем вдвое пакетов по сравнению с другими наиболее популярными реестрами пакетов (одним их которых является хранилище Apache Maven). Фактически, в настоящее время это самый крупный реестр пакетов в мире.

Теперь давайте промотаем время вперед на восемь месяцев, и в настоящее время в реестре NPM имеется около 500 000 пакетов. Это огромный рост по сравнению с другими хранилищами пакетов.

Будучи фронт-энд разработчиком на JavaScript, важно не отставать от современных инструментов и библиотек JavaScript. Когда технология становится популярной, спрос на нее высок, что, в свою очередь, означает больше заданий по кодированию, за которые платят самую высокую стоимость в отрасли. Поэтому мы собрали список популярных технологий JavaScript, которые, как мы думаем, вам следует знать.

Библиотеки

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

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

React — это библиотека JavaScript, созданная разработчиками Facebook и Instagram. React была признана самой любимой технологией среди разработчиков, согласно опросу Stack Overflow Survey 2020. React также является самым популярным проектом JavaScript, основываясь на подсчете звезд GitHub.

Так почему React привлекает столько внимания? С помощью React можно создать интерактивный интерфейс с использованием декларативного подхода, в котором вы можете контролировать состояние приложения, говоря «картинка должна выглядеть так». Он использует компонентную модель, в которой компоненты являются многократно используемыми элементами пользовательского интерфейса, и каждый компонент имеет свое собственное состояние.

React использует виртуальный DOM, так что вам не нужно беспокоиться о прямом его манипулировании. Другие примечательные особенности React включают в себя односторонний поток данных, дополнительный синтаксис JSX и инструмент командной строки для создания проекта React с нулевой конфигурацией сборки.

jQuery — это библиотека, которая сделала JavaScript более доступным, а манипуляции с DOM проще, чем раньше. Мягкая кривая обучения jQuery и простой синтаксис породили поколение новых клиентских разработчиков. Несколько лет назад jQuery считался надежным решением для создания мощных веб-сайтов с кросс-браузерной поддержкой. Основные функции jQuery, такие как манипулирование DOM на основе селекторов CSS, обработка событий и создание вызовов AJAX, подпитывали ее популярность.

Однако все изменилось, и среда JavaScript постоянно развивается. Некоторые функции jQuery были включены в новую спецификацию ECMAScript. Более того, новые библиотеки и фреймворки, используемые сегодня, имеют собственный способ связывания DOM, и поэтому простые методы манипуляции с DOM больше не требуются. Популярность jQuery находится на спаде, но я не думаю, что он исчезнет в ближайшее время.

D3 (или D3.js) — мощная библиотека JavaScript для создания интерактивных визуализаций с использованием веб-стандартов, таких как SVG, HTML и CSS. В отличие от других библиотек визуализации, D3 предлагает лучший контроль над окончательным визуальным результатом.

D3 работает, связывая данные с DOM и затем преобразуя их в документ. Он также имеет собственную экосистему, которая состоит из плагинов и библиотек, которые расширяют ее базовые функциональные возможности. Библиотека существует с 2011 года, и в ней есть множество документации и учебников, которые помогут вам начать работу.

Если вы хотите создать простые визуализации, не вкладывая слишком много времени в них, вы должны проверить Chart.js.

Фреймворки

Фреймворк имеет архитектуру, которая диктует поток управления в вашем приложении. Он описывает основу и рассказывает вам, как все должно быть организовано. Вам также предоставляются основные функции, необходимые для запуска и работы приложения. Кроме того, вы обязаны следовать принципам и шаблонам фреймворка. Разница между фреймворком и библиотекой заключается в том, что вы вызываете библиотеку, тогда как фреймворк вызывает вас.

Он часто включает в себя множество библиотек и имеет более высокий уровень абстракции. Функциональность, такая как обработка событий, создание вызовов AJAX, привязка шаблонов и данных и тестирование, встроены во фреймворк.

AngularJS когда-то была самой популярной технологией JavaScript среди разработчиков интерфейсов. Она был поддержана Google и сообществом частных лиц и корпораций. Несмотря на популярность, у AngularJS была своя доля недостатков. Команда провела два года работы над новой версией Angular, которая была, наконец, выпущена в сентябре 2020 года.

Выпуск Angular 2 был переделкой AngularJS. Некоторые из функций Angular 2 включают:

  • TypeScript поверх JavaScript как язык по умолчанию
  • компонентная архитектура
  • улучшенная производительность как на мобильных, так и на веб-платформах
  • лучшие инструменты и варианты скаффолдинга

Тем не менее, модернизация от Angular 1.x до Angular 2 является дорогостоящей, потому что Angular 2 — совершенно другой зверь. Это одна из причин, почему у Angular 2 не было такой же скорости принятия, как у ее предшественника. Но Angular и AngularJS по-прежнему относятся к числу наиболее часто используемых технологий в соответствии с Stack Overflow (2020). Проект имеет около 28 000 звезд в GitHub.

Vue.js — это легкая инфраструктура JavaScript, которая в этом году была в тренде. Это самый популярный фреймворк JavaScript на GitHub с точки зрения звезд GitHub. Синтаксис шаблона на основе HTML связывает предоставленный DOM с данными экземпляра.

Мастер Йода рекомендует:  Практическое применение ООП в PHP5 PHP

Фреймворк предлагает опыт, похожий на React, с его виртуальными DOM и компонентами многократного использования, которые можно использовать для создания как виджетов, так и целых веб-приложений. Кроме того, вы также можете использовать синтаксис JSX для непосредственного написания функций рендеринга. Когда состояние изменяется, Vue.js использует систему реактивности, чтобы определить, что изменилось и перераспределяет минимальное количество компонентов. Vue.js также поддерживает интеграцию других библиотек во фремворк без особых хлопот.

Ember.js является интерфейсом на основе шаблона Model-View-ViewModel (MVVM). Он следует за стандартным подходом к настройке, который популярен среди сторонних фреймворков, таких как Ruby on Rails и Laravel. Ember.js включает в себя общие идиомы и лучшие практики фреймворков, чтобы вы могли создать приложение без особых усилий.

Стек Ember обычно включает:

  • Ember CLI: предоставляет основные варианты скаффолдинга и поддерживает сотни надстроек.
  • Ember Data: библиотека сохранения данных, которая может быть настроена для работы с любым сервером.
  • Ember Inspector: расширение доступно для Chrome и Firefox.
  • Liqu >Инструменты

Инструмент представляет собой набор подпрограмм, которые помогут вам в процессе разработки. В отличие от библиотеки, инструмент обычно выполняет задачу на клиентском коде. Он берет ваш код в качестве входных данных, выполняет на нем задачу, а затем возвращает результат. Обычно используемые инструменты включают в себя транспиляторы и инструменты для сборки, активаторы, модули и инструменты для скаффолдинга.

Инструменты: универсальные исполнители задач

Универсальные исполнители задачи — это инструменты, используемые для автоматизации определенных повторяющихся задач. В число популярных исполнителей задач входят:

Gulp — это инструментарий JavaScript, который используется как исполнитель задач и как система сборки в веб-разработке. Компиляция, минимизация кода, оптимизация изображения, модульное тестирование, листинг и т.д. — это повторяющиеся задачи, которые должны быть автоматизированы. Gulp упрощает процесс написания задач даже для людей, которые менее знакомы с JavaScript.

Gulp использует конвейеры для потоковой передачи данных из одного плагина в другой, и конечный результат выводится в папку назначения. Gulp работает лучше по сравнению с Grunt, потому что он не создает временные файлы для хранения промежуточных результатов, что приводит к меньшему количеству вызовов ввода-вывода.

Grunt — это исполнитель задач и инструмент автоматизации JavaScript. Grunt имеет интерфейс командной строки, который позволяет запускать настраиваемые задачи, определенные в файле, называемом Gruntfile. У Grunt есть тысячи плагинов на выбор, которые должны охватывать большинство обычных повторяющихся задач, с которыми вы столкнулись. С помощью Grunt вы можете запускать все задачи под одной командой, что упрощает вашу жизнь.

Gulp и Grunt требуют, чтобы вы потратили время на изучение и освоение нового инструмента, что займет у вас так же время. Ввода дополнительных зависимостей в ваш проект можно избежать, выбирая альтернативу, которая уже связана с Node.js. Хотя npm больше известен как менеджер пакетов, сценарии npm можно использовать для выполнения основной части вышеупомянутых задач.

Инструменты: тестирование

Тестирование — это процесс утверждения и проверки того, что приложение соответствует ожидаемым бизнес-требованиям и техническим требованиям. Подход, основанный на испытаниях, также помогает обнаруживать ошибки и, следовательно, следует рассматривать как неотъемлемую часть современного интерфейса разработки.

Jest — это относительно новая платформа тестирования, созданная Facebook и хорошо принятая сообществом React. Существует распространенное заблуждение, что Jest специально разработан для работы с React; однако, согласно документации Jest:

Несмотря на то, что Jest можно рассматривать как тест, специфичный для React, на самом деле это универсальная платформа тестирования, способная адаптироваться к любой библиотеке или фреймворку JavaScript. Вы можете использовать Jest для проверки кода JavaScript.

Самое большое преимущество использования Jest перед другими наборами тестов заключается в том, что вам требуется нулевая или минимальная конфигурация для начала написания тестов. Фреймворк имеет встроенную библиотеку утверждений и поддерживает использование макетных функций или шпионов.

Jest имеет функцию под названием «snapshot testing», которая позволяет гарантировать, что пользовательский интерфейс приложения не изменится неожиданно. Разработчики из Facebook и другие участники вложили много работы в этот проект, поэтому не удивительно, что Jest окажется самой популярной платформой для тестирования JavaScript в ближайшие годы.

Mocha — это платформа тестирования JavaScript, которая имеет поддержку браузера, поддержку асинхронного обслуживания, включая перспективы, отчеты об охвате тестирования и JavaScript API для запуска тестов. Mocha часто соединяется с библиотекой утверждений, такой как Chai, should.js, expect.js, потому что у нее нет собственной библиотеки утверждений.

Jasmine — это ориентированный на поведение фреймворк JavaScript. Жасмин стремится стать браузером, платформой и независимым от фреймворка набором тестов. У Jasmine есть своя собственная библиотека утверждений, называемая matchers, которая дает инструменту чистый и легко читаемый синтаксис. Jasmine не имеет встроенного тестового исполнителя, и вам, возможно, придется использовать общий тестовый исполнитель, например, Karma.

В заключении

JavaScript остался актуальным со времен его создания еще в 1995 году. Вероятно, он останется таким же, пока браузеры не решат отказаться от него ради другого языка. Несмотря на то, что существует множество других языков, которые компилируются с использованием JavaScript, нет другого языка сценариев, который заменит JavaScript в обозримом будущем. Почему? Потому что JavaScript стал слишком популярным, чтобы его можно было заменить.

Язык не лишен кривых обучения, и есть множество фреймворков и библиотек, которые помогут вам заняться его изучением. Если вы ищете дополнительные ресурсы для изучения или использования языка в своей работе, то в Интернете вы сможете найти массу полезных ресурсов на эту тему.

Среда JavaScript определенно развивается, что видно из текущих тенденций в веб-разработке. Старые библиотеки и фреймворки были заменены новыми технологиями. jQuery, которая когда-то была наиболее популярной библиотекой JavaScript, испытывает некоторый спад с точки зрения привлекательности, использования и популярности. Новое поколение интерфейсных библиотек, фреймворков и инструментов набирает силу и получает всеобщее признание.

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

Справочник современных концепций JavaScript: часть 2

Изучите область видимости, замыкания, потоки данных и концепции, широко используемые в современных JavaScript фреймворках и приложениях

Кратко: В первой части серии «Справочник современных концепций JavaScript» мы узнали о функциональном, реактивном и функциональном реактивном программировании. Во второй части мы познакомимся с понятиями область видимости, замыкания, tree shaking, компоненты и другими, а также из темы JavaScript приложений: поток данных и обнаружение изменений.

Введение

За последние годы JavaScript сильно развился и не думает на этом останавливаться. Однако множество концепций, рождающихся в JavaScript блогах и документациях, так и остаются невостребованными широким кругом разработчиков интерфейсов. В настоящей серии статей мы изучим концепции, требующие как среднего, так и продвинутого уровней подготовки, а также рассмотрим, как они вписываются в современный JavaScript: фреймворки и приложения.

Концепции

В этой статье мы рассмотрим концепции, имеющие решающее значение для понимания современного JavaScript и JavaScript приложений, включая:

  • Область видимости (глобальная, локальная, лексическая) и замыкания
  • Однонаправленный поток данных и двухсторонняя привязка данных
  • Обнаружение изменений в JavaScript фреймворке: грязная проверка, аксессоры, виртуальный DOM
  • Веб-компоненты
  • Умные и глупые компоненты
  • JIT (Just-In-Time) компиляция
  • AOT (Ahead-of-Time) компиляция
  • Tree shaking

Область видимости (глобальная, локальная, лексическая) и замыкания

Объяснение замыканий — печально известный технический вопрос о JavaScript. Правда в том, что многие опытные разработчики JavaScript не могут объяснить замыкания, даже если они концептуально понимают (и даже используют) их. Давайте немного уйдем в сторону и прежде всего поговорим о концепциях, необходимых для объяснения замыканий.

Область видимости

Для того, чтобы разобраться с замыканием, нам нужно сначала понять область видимости. Область видимости — это просто контекст нашего кода: там, где доступны переменные и функции.

Следующий пример демонстрирует глобальную и локальную области видимости:

Весь код имеет доступ к глобальной области видимости. Если мы откроем пустой .js файл и наберем var globalVar , эта переменная будет доступна для всего, что мы напишем далее. Если мы выполним файл в браузере, глобальной областью видимости globalVar будет window .

Примечание: Если мы объявим новую переменную без ключевого слова var , она будет помещена в глобальную область видимости независимо от того, где она находится в коде. Возможно, вы уже с этим сталкивались.

Функция someFunction создает свою собственную локальную область видимости. Она также имеет доступ к глобальной области видимости: внутри someFunction мы можем без ограничений использовать globalVar . Тем не менее, глобальная область видимости не имеет доступа к вложенным контекстам, таким как локальная область видимости someFunction . Если мы попытаемся залогировать localVar из глобальной области видимости, мы получим ошибку, потому что localVar не определен в глобальной области видимости.

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

Лексическая область видимости (или статическая область видимости) закрепляет то, что каждая вложенная функция может обращаться к родительским функциям.

Рассмотрим следующий пример:

Этот код доступен в JSFiddle: JS Scope (откройте консоль браузера, чтобы увидеть результат).

innerFunc — самая внутренняя функция. Она объявлена внутри middleFunc , которая, в свою очередь, объявлена в outerFunc .

Функция innerFunc может обращаться к переменным, объявленным во всех родительских областях видимости. Эта цепочка областей видимости обеспечивает доступ к:

  • a из глобальной области видимости;
  • b из outerFunc ;
  • c из middleFunc ;
  • d из собственной локальной области видимости innerFunc .

Это работает только в сторону углубления во вложенные функции, а не наоборот. Например, переменная d с локальной областью видимости объявлена в innerFunc и недоступна для middleFunc , outerFunc или глобальной области видимости.

Замыкания

В первой части cправочника современных концепций JavaScript мы узнали о функциях и функциях высшего порядка в качестве объектов первого класса. Если звучит незнакомо, найдите минутку, чтобы ознакомиться с разделом о функциях высшего порядка.

Теперь давайте перейдем к примеру функции высшего порядка, который мы видели в первой части:

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

Замыкание создается, когда функция ( alertGreeting ), объявленная внутри внешней функции ( whenMeetingJohn ), ссылается на переменные из локальной области видимости внешней функции (такие как переменная greeting ).

Замыканием называется функция, связанная с функцией и лексическим окружением (любые локальные переменные, которые были в области видимости при создании замыкания), в которых она была объявлена.

Когда мы вызываем atLunchToday() , мы получаем alert с аргументом, переданным при присвоении whenMeetingJohn(‘Hi’) (в данном случае ‘Hi’ ), и переменной greeting , доступной в лексическом окружении alertGreeting .

Примечание: Мы также можем вызвать возвращаемую функцию ( alertGreeting ), не присваивая ее. Делается это так: whenMeetingJohn(‘Whassup’)() .

Надеюсь, вы можете оценить важность замыканий, глядя на этот простой пример. Мы можем приветствовать Джона несколькими различными приветствиями. Каждый раз мы создаем замыкание с доступом к конкретным данным приветствия в области видимости на момент создания.

В другом распространенном примере, демонстрирующем замыкания, используется простое выражение сложения:

Оба add1 и add5 — замыкания с различными лексическими окружениями, хранящими разные значения для аргумента x . Эти значения защищены тем, что они «заключены» в лексическое окружение каждого замыкания. Мы могли бы использовать фабричную функцию addCreator(x) для создания стольких функций add_ , сколько нам потребуется.

Подводя итог: область видимости и замыкания

Область видимости — это то, что многие разработчики JavaScript изучают раньше всего, но не могут объяснить словами или конкретными примерами. Понимание области видимости важно для написания хорошего JavaScript.

Примечание: Здесь мы обговорили далеко не все об области видимости. Для более глубокого понимания, особенно в отношении ключевого слова this, существует несколько отличных ресурсов. Больше ссылок ищите ниже.

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

Дополнительную информацию об области видимости и замыканиях (и this ) можно найти на следующих ресурсах:

Однонаправленный поток данных и двухсторонняя привязка данных

С распространением фреймворков JavaScript и одностраничных приложений (SPA) для разработчиков JavaScript стало особенно важно понимать такие понятия как поток и привязка данных, а также то, как используемые нами инструменты работают с ними.

Однонаправленный поток данных

Приложение или среда с однонаправленным потоком данных использует модель как единственный источник правды. React — яркий представитель однонаправленного потока данных (или односторонней привязки данных). Сообщения отправляются из пользовательского интерфейса в форме событий, чтобы оповестить модель и она обновилась.

Взгляните на следующий пример на React:

Мы видим, что state (объект модели) задается в функции-конструкторе. Начальное значение this.state.text — пустая строка. В нашей функции render() мы добавляем обработчик onChange к элементу . Мы используем этот обработчик для setState() , оповещая state , что необходимо обновить свойство text новым значением из инпута.

Данные текут только в одном направлении: от модели вниз. Инпут не имеет прямого доступа к модели. Если мы хотим обновить состояние в ответ на изменения из пользовательского интерфейса, инпут должен отправить сообщение со всей необходимой информацией. Единственный способ, которым пользовательский интерфейс может влиять на модель, — это событие и метод setState(). Пользовательский интерфейс никогда магическим образом не обновляет модель.

Примечание: Чтобы пользовательский интерфейс отобразил произошедшие в модели изменения, React создает новый виртуальный DOM и сопоставляет его со старым виртуальным DOM. Затем в реальном DOM отображаются только изменения. Мы поговорим об этом подробнее в разделе об обнаружении изменений.

Двусторонняя привязка данных

При двусторонней привязке данных данные передаются в обоих направлениях. Это означает, что обновить модель может как JavaScript, так и пользовательский интерфейс. Наиболее ярким примером такого подхода является AngularJS.

Примечание: В этой статье под AngularJS подразумевается версия 1.x, в то время как под Angular — версии 2.x и выше в соответствии с руководством по брендингу для Angular.

Давайте реализуем верхний пример, но с помощью AngularJS и двухсторонней привязки данных:

В нашем контроллере мы настроили модель $scope.text . В шаблоне мы связываем эту модель с , используя ng-model=»text» . Когда мы меняем значение инпута в пользовательском интерфейсе, модель также обновляется в контроллере. Это можно увидеть в $watch() .

Примечание: Использование $watch() в контроллере — дискуссионная практика. Здесь мы сделали это для примера. В своих приложениях AngularJS учтите, что существуют альтернативы использованию $watch() в контроллерах (например, события), и если вы все-таки используете $watch() , всегда отменяйте своих наблюдателей $onDestroy.

Это двухсторонняя привязка данных в AngularJS. Как вы можете видеть, мы не настраивали какие-либо события или обработчики, чтобы явно сигнализировать контроллеру, что модель была обновлена ​​в пользовательском интерфейсе. Привязка данных text в шаблоне автоматически использует наблюдателя для отображения изменений в модели. Мы также можем наблюдать ( $watch() ) модель. Обычно наблюдение должно выполняться в службах или в директивных функциях link , а не в контроллерах.

Примечание: Для сравнения нового значения с предыдущим AngularJS использует так называемый цикл дайджеста (грязную проверку). Вы можете больше узнать о грязной проверке в AngularJS в разделе об обнаружении изменений.

Дополнительная информация: Двухсторонняя привязка данных в Angular

Но подождите! У Angular (v2 +) есть «банан в коробке» [(ngModel)] , верно ведь? На первый взгляд, это может показаться продолжающейся магией двусторонней привязки данных. Однако это не так. Синтаксис двухсторонней привязки Angular — [()] просто сокращает для вас свойство и привязку события в шаблоне, а директива ngModel предоставляет вам событие ngModelChange . Чтобы глубже в этом разобраться, ознакомьтесь со статьей о двухсторонней привязке в Angular.

Следующий пример функционально эквивалентен и демонстрирует директиву ngModel :

Подводя итог: однонаправленный поток данных и двухсторонняя привязка данных

Многие современные JavaScript фреймворки и библиотеки используют однонаправленный поток данных (React, Angular, Inferno, Redux и так далее). Почему? Однонаправленный поток данных поддерживает архитектуру в чистоте, уделяя внимание тому, как приложение работает с данными. Управление состоянием приложения также становится проще, обновления более предсказуемы, а производительность возрастает.

Хотя магия двухсторонней привязки данных была одной из самых популярных функциональностей демоверсий AngularJS еще в 2009 году, Angular оставил ее в прошлом. В начале некоторые разработчики Angular жаловались на это, но в конечном итоге многие согласились, что прирост производительности и больший контроль перевешивают удобство «магии».

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

Примечание: Обычно, когда разработчики упоминают «внедрение двухсторонней привязки данных» в фреймворках с однонаправленным потоком данных (например, React), они имеют ввиду действия, которые необходимо предпринять для уведомления модели об изменении пользовательского интерфейса. Они не имеют ввиду способ реализации магии двухсторонней привязки.

Дополнительную информацию об однонаправленном потоке данных и двухсторонней привязке данных можно найти на следующих ресурсах:

Обнаружение изменений в JavaScript фреймворке: грязная проверка, аксессоры, виртуальный DOM

Обнаружение изменений важно для любого динамического одностраничного приложения (SPA). Когда пользователь что-то обновляет, у приложения должен быть способ обнаружить и отреагировать на это изменение соответствующим образом. Поэтому для SPA-структур жизненно важно выявлять изменения.

Давайте на довольно высоком уровне рассмотрим несколько методов обнаружения изменений, используемых сегодня в популярных фреймворках JavaScript.

Грязная проверка

Хотя уже существует Angular, на AngularJS все еще работает или прямо сейчас находится разработке множество приложений. Для обнаружения изменений в приложении AngularJS использует так называемый цикл дайджеста. Под капотом цикл дайджеста использует грязную проверку. Что же это значит?

Грязная проверка осуществляет глубокое сравнение, выполняемое для всех моделей в представлении, чтобы проверить измененное значение. Цикл дайджестов AngularJS добавляет наблюдателя для каждого свойства, которое мы добавляем к $scope и привязываем в пользовательском интерфейсе. Еще один наблюдатель добавляется, когда мы отслеживаем значения изменений с помощью $scope.$watch() .

«AngularJS запоминает значение и сравнивает его с предыдущим значением. Это стандартная грязная проверка. Если изменение в значении есть, то он запускает событие изменения», — Мишко Хевери , создатель AngularJS и Angular

Цикл дайджеста — это цикл. AngularJS запускает свой список наблюдателей и проверяет, не изменилась ли какая-либо из наблюдаемых переменных $scope (иначе они «грязные»). Если переменная не изменилась, он переходит к следующей наблюдаемой переменной. Если он находит «грязную» переменную, он запоминает новое значение и снова входит в цикл. Когда никакие новые изменения не обнаружены во всем списке наблюдения, обновляется DOM.

Основными преимуществами грязной проверки являются простота и предсказуемость: нет расширения объектов и не нужно пользоваться никаким API. Однако она неэффективна. Всякий раз, когда что-либо меняется, запускается цикл дайджеста. Поэтому при создании наблюдателей в AngularJS очень важно соблюдать осторожность. Каждый раз, когда свойство $scope привязывается к пользовательскому интерфейсу, добавляется наблюдатель. Каждый раз, когда используется $watch() , добавляется еще один наблюдатель. Многие директивы также добавляют наблюдателей, а также переменные области видимости, фильтры и повторители.

Хотя грязная проверка достаточно быстра в простом приложении, ситуация легко может выйти из-под контроля в сложной реализации. Это привело к таким статьям, как 11 советов по улучшению производительности AngularJS: 1. минимизация/избегание наблюдателей и Ускорение цикла дайджеста в AngularJS.

Аксессоры

Ember и Backbone используют аксессоры к данным ( геттеры и сеттеры) для обнаружения изменений. Объекты Ember наследуются от API Ember и имеют методы get() и set(), используемые для обновления моделей с привязкой данных. Это позволяет связать пользовательский интерфейс и модель данных, чтобы Ember узнал, что именно изменилось. В свою очередь, только модифицированные данные производят события для обновления приложения.

Примечание: В Backbone это делается с помощью моделей Backbone с методами get() и set().

Такой подход очень прост и требует, чтобы автор приложения хорошо продумывал свои привязки данных. Однако, с другой стороны, иногда это может приводить к путанице, потому что Ember.Object используются только при привязке данных к шаблонам. Если привязки данных пользовательского интерфейса не было, обновления не используют Ember.Objects . Такой смешанный подход может привести к тому, что разработчик в недоумении чешет голову, когда что-то не обновляется из-за забытого сеттера или геттера.

Виртуальный DOM

В качестве реализации обнаружения изменений React и Inferno.js используют виртуальный DOM. React не пытается определить каждое отдельное изменение. Вместо этого при изменении виртуальный DOM сравнивает предыдущее состояние пользовательского интерфейса и новое. React уведомляется об этих изменениях с помощью метода setState(), который запускает метод render() для восполнения разницы.

Виртуальный DOM (иногда называемый V-DOM) представляет собой модель данных JavaScript, представляющую реальное дерево DOM.После генерации виртуального DOM, в браузере ничего не отображается. Старая модель сравнивается с новой моделью и после того, как React определит, какие части виртуального DOM были изменены, только они исправляются в реальном DOM.

Подводя итог: обнаружение изменений в JavaScript фреймворке

Есть много способов, которыми JavaScript фреймворки управляют обнаружением изменений, включая такие, которые не были рассмотрены здесь. У каждого из них есть свои сильные и слабые стороны, но современная тенденция направлена ​​на более продуманные и менее автоматические методы, многие из которых используют под капотом паттерн наблюдателя.

Дополнительную информацию об обнаружении изменений в JavaScript фреймворке можно найти на следующих ресурсах:

Веб-компоненты

Веб-компоненты представляют собой инкапсулированные, многоразовые виджеты, основанные на API веб-платформы. Они базируются на четырех стандартах:

Веб-компоненты позволяют нам создавать и импортировать пользовательские элементы, автоматически связывающие JavaScript с шаблонами и использующие теневой DOM для инкапсуляции DOM и CSS.

Веб-компоненты состоят из связки различных API веб-платформы. Существуют библиотеки (такие как Polymer) и полифилы (например, webcomponents.js) для устранения разрыва между текущей и будущей поддержкой браузеров.

Предположим, мы хотим создать простой веб-компонент ( my-component ), показывающий статический текст. Мы хотели бы использовать атрибуты HTML, чтобы заставить компонент менять цвет текста и выводить что-нибудь в консоль. Для отображения нашего пользовательского элемента на нашем сайте или в приложении, мы можем его импортировать и использовать вот так:

Чтобы создать компонент my-component с использованием теневого DOM, наш my-component.html может выглядеть примерно так:

определяет CSS стиль и HTML разметку элемента. Затем, чтобы воспользоваться преимуществами теневого DOM и функциональности JavaScript, мы добавляем тег

Добавить комментарий