Давайте создадим одностраничное приложение с натуральными волосами, используя ванильный JavaScript (ES6)!

Знания, необходимые для выполнения этой серии руководств

  1. Базовое понимание синтаксиса JS: объявление переменных, доступ к значениям объекта, итерация по массиву, написание функции и т. Д.
  2. ES6 - это хорошо, но не обязательно
  3. Желание что-то построить!

Обзор серии учебных пособий

Когда я изучал JS, я столкнулся с множеством упражнений и алгоритмов, таких как «FuzzBuzz», и создания JS-функций, которые выполняли такие вещи, как использование двух или более массивов для возврата нового массива уникальных значений в порядке исходных предоставленных массивов. Короче говоря, я узнал о синтаксисе JS, но ничего, что пролило бы свет на то, как применить полученные знания для создания настоящего веб-приложения. Это руководство сделает именно это. Покажите, как JS используется в веб-разработке, там будет немного теории, объяснения концепции и, конечно же, практического упражнения. Так что, пожалуйста, продолжайте!

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

  1. Чтение: динамическое отображение данных (вы здесь)
  2. Создание: разрешить ввод данных пользователем
  3. Апдатин г / Редактирование
  4. Удаление

Что вы построите

Вы создадите веб-сайт с естественной прической, на котором пользователи смогут просматривать различные стили (читать), добавлять новые стили (создавать), редактировать стили (обновлять) и удалять стили. Пользователи смогут фильтровать, какие стили они видят по сложности.

Давайте начнем учебник!

Что такое чтение?

Большую часть интерфейсной веб-разработки можно свести к «отображению информации». Информация в этом контексте - d-a-t-a. Возьмем реальный пример: Twitter. Твиттер имеет базу данных, в которой хранятся все твиты, которые когда-либо публиковались. Когда вы заходите в свою ленту, вы видите, как Twitter выбирает отображение данных твитов, которые хранятся для всех твитов, которые у вас есть в вашей ленте.

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

{
  "author": "Lunionsuite",
  "author_handle": "LunionSuite",
  "created": "March 20th, 2019,
  "text": "Who's ready for mango season? :tounge-out:",
  "picture": "http://linktohostedimage.com",
  "likes": 3,507,
  "retweets": 1,123,
  "comments": 53
}

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

Шаги развития

К концу этого первого урока из серии ваш сайт будет выглядеть так:

Давайте поговорим о том, что нужно сделать, чтобы добраться сюда:

  1. Настройка проекта
  2. Создайте единую карточку с использованием HTML с жестко заданными значениями
  3. Динамическое создание одной карты с помощью JS
  4. Статическое добавление информации в элементы HTML с помощью JavaScript
  5. Динамическое добавление информации в элементы HTML с помощью JavaScript
  6. Динамически создавать весь список из 10 - - данных

1) Настройка проекта

  • Для этой серии руководств я рекомендую писать код с помощью codeandbox.io (регистрация не требуется). Вы также можете использовать любой редактор кода, например Visual Studio Code, Sublime и т. Д.
  • Независимо от того, какую программу кодирования вы выберете, убедитесь, что вы начинаете с трех файлов: index.html, index.js и styles.css. Последние два файла должны находиться в папке с именем src. И каждый файл должен выглядеть следующим образом:
// index.html
<!DOCTYPE html>
<html>
  <head>
   <title>Natural HairStyle Site</title>
   <meta charset="UTF-8" />
   <link rel="stylesheet" type="text/css" href="./src/styles.css" />
  </head>
 <body>
  <script src="src/index.js"></script>
 </body>
</html>
// index.js (completely empty)
// styles.css
body {
  font-family: sans-serif;
  width: 50%;
  margin: auto;
}
  • В конце каждого шага будет ссылка на проект с окончательным кодом для этого шага.

Код шага 1: здесь

2) Создайте единую карточку с использованием HTML с жестко заданными значениями

На этом шаге вы разберете пользовательский интерфейс (UI) на HTML, чтобы динамически воссоздать его в JavaScript на следующем шаге.

Сначала подумайте, как должен выглядеть окончательный пользовательский интерфейс для одной «карты» и элементы HTML, необходимые для ее создания:

Примечание: благодаря популярности JS-фреймворков, таких как React, Angular и т. Д., Этот подход к рассмотрению окончательного пользовательского интерфейса для определения строительных блоков, необходимых для его создания, теперь является стандартной частью интерфейсной разработки!

Определите простой HTML:

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

// index.html (inside of the <body>)
<div>
 <h4>
   <a></a>
 </h4>
 <img />
</div>

Если вы раскрутите его, то увидите, что это далеко не так, как должен выглядеть окончательный интерфейс. И это нормально! Это ожидаемо, поскольку вы не указали, что должен содержать каждый элемент HTML. Возвращаясь к окончательному пользовательскому интерфейсу, вы знаете, что хотите:

  • a в h4: 1) указывает на URL-адрес прически и 2) отображает это название прически.
  • img должен получить URL-адрес изображения прически.

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

Данные для первой прически:

{
id: 1,
pic: "https://i0.wp.com/therighthairstyles.com/wp-content/uploads/2014/03/13-flat-twist-with-twist-out-2.jpg?w=500&ssl=1",
name: "Flat-Twist With Twist Out",
difficulty: "Medium",
info: "https://therighthairstyles.com/20-most-inspiring-natural-hairstyles-for-short-hair/"
}

Как значения в этом объекте сопоставляются с HTML, необходимым для создания карточки?

Собираем HTML вместе

// HTML for a single card
<div>
 <h4>
    <a href="https://therighthairstyles.com/20-most-inspiring-  natural-hairstyles-for-short-hair/">
    Flat-Twist With Twist Out
   </a>
 </h4>
<img src="https://i0.wp.com/therighthairstyles.com/wp-content/uploads/2014/03/13-flat-twist-with-twist-out-2.jpg?w=500&ssl=1"/>
</div>

Здесь вы можете видеть, что href для a должен быть скопирован из ключа info в данных. И src для img следует скопировать из значения pic из данных.

Теперь ваш интерфейс должен выглядеть так:

Это намного лучше, чем раньше! НО все же это выглядит немного забавно, потому что изображение очень большое, особенно в отношении заголовка. Вы можете создавать и добавлять стили в свой CSS.

img {
 width: 80%;
 height: 100%;
}
.card {
 box-shadow: 10px 10px 5px 0px rgba(238, 238, 238, 1);
 margin: 15px;
 text-align: center;
 padding-bottom: 10px;
}

Обновлен HTML (в div добавлен класс card)

// HTML for a single card
<div class="card">
<h4>
    <a href="https://therighthairstyles.com/20-most-inspiring-  natural-hairstyles-for-short-hair/">
    Flat-Twist With Twist Out
    </a>
 </h4>
<img src="https://i0.wp.com/therighthairstyles.com/wp-content/uploads/2014/03/13-flat-twist-with-twist-out-2.jpg?w=500&ssl=1">
</div>

Карточка с одной прической теперь выглядит так:

Окончательный код для шага 2 можно найти: здесь

Теперь вы готовы динамически создавать эту карточку с помощью JavaScript!

3) Создайте одну карту динамически с помощью JS

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

  • Название прически,
  • Ссылка на веб-страницу с дополнительной информацией о прическе и
  • Источник изображения

все были введены непосредственно в HTML.

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

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

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

Итак, сначала давайте рассмотрим, как создать элемент HTML в JavaScript. Но сначала не забудьте закомментировать HTML-код карточки, который был добавлен в index.html на предыдущем шаге.

Создавайте элементы HTML с помощью JavaScript

Одна из многих причин, по которым JavaScript так популярен, заключается в том, что вы можете использовать его для создания динамического HTML. Иногда это называют манипулированием DOM. DOM = объектная модель документа. Сейчас важно знать, что это представление HTML, к которому JS имеет доступ и может добавлять / удалять / редактировать HTML.

Давайте посмотрим на синтаксис для создания HTML-элемента в JS:

document.createElement('elementName')

Здесь следует отметить несколько моментов:

  • document - это собственный объект JS, он представляет HTML, в который JS вносит изменения. Нативный означает, что вам не нужно его объявлять (var document), чтобы использовать.
  • .createElement('elementName') - это функция, которая есть у document. Он отвечает за создание новых элементов. Требуется 1 параметр и это имя элемента, который должен быть создан (кавычки необходимы).
  • elementName это имя HTML-элемента, который вы хотите создать. 'div' для создания div, 'p' для p и т. Д.

Возвращаясь к полному HTML из предыдущего шага, чтобы создать карточку, необходимы следующие элементы HTML: div, h4, a и img. Как бы вы создали их на JS?

Их можно создать так:

// index.js
const div = document.createElement('div')
const h4 = document.createElement('h4')
const a = document.createElement('a')
const img = document.createElement('img')

constants были созданы для хранения ссылки на вновь созданные элементы. Это важно, потому что позже на этом этапе этими элементами будут управлять (добавление имен классов, атрибутов и т. Д.) И добавление constant для каждого элемента, что позволяет настроить таргетинг на каждый элемент, как вы увидите ниже. Также обратите внимание, что constant имена не обязательно должны совпадать с именами вновь созданных элементов. Они могли быть кем угодно. Однако, поскольку они будут использоваться для ссылки на созданные элементы, имеет смысл дать им соответствующие имена для большей ясности. Вы также можете использовать var или let вместо const.

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

Добавление элементов в DOM

Для добавления элементов в DOM есть метод append. Работает это так:

parentElement.append(element)

Чтобы разбить это на части: append берет элемент и добавляет его в качестве последнего дочернего элемента внутри другого элемента (parentElement).

Рассмотрим случай с ранее созданным div, который станет контейнером для карты. Что бы было за parentElement, чтобы добавить этот элемент в DOM?

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

<!DOCTYPE html>
<html>
  <head>
    <title>Natural Hairstyles</title>
  </head>
  <body>
    <h3>Natural Hairstyles Website</h3>
    <!-- HTML for card here -->
  </body>
<html>

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

// Remember the syntax for appending elements
// parentElement.append(element)
// You want to add the div to the body
// while div is a constant you previously created
// body is not. It must be created

const body = document.querySelector('body');
// querySelector takes a selector and returns the element that matches the selector from the DOM. The selectors are just like CSS selectors: .class, #id, element, etc
// Now you can do:
body.append(div)

HTML был обновлен следующим образом:

// Resulting HTML
<!DOCTYPE html>
<html>
  <head>
    <title>Natural Hairstyles</title>
  </head>
<body>
    <h3>Natural Hairstyles Website</h3>
    <div></div>
</body>
<html>

Приятно, что div теперь там! Как бы вы добавили оставшиеся элементы HTML в DOM?

// Add the anchor tag inside of the h4
h4.append(a)
// Add the h4 inside the div
div.append(h4)
// Add the img inside the div
div.append(img)

Результирующий HTML

<body>
    
   <h3>Natural Hairstyles Website</h3>
   <div>
      <h4>
        <a></a>
      </h4>
      <img />
   </div>
</body>

Примечание: когда дело доходит до добавления элементов к другим элементам, порядок имеет значение. Проверьте это, выполнив div.append(img) до div.append(h4). Что меняется?

Теперь вы динамически создали HTML-код, необходимый для карточки, в JS.

Окончательный код для этого шага: здесь

Теперь поработаем над заполнением HTML-содержимого с помощью JavaScript.

4) Статическое добавление информации в элементы HTML с помощью JavaScript

Надеюсь, вы попробовали это! Теперь займемся следующей проблемой. Хотя структура HTML карты теперь правильно построена с помощью JS, отсутствуют некоторые элементы:

  1. В их содержимом a должно отображаться название прически.
  2. Их атрибуты: a имеет атрибут href, который должен быть установлен на URL-адрес для получения дополнительной информации о прическе, img имеет атрибут src, который должен указывать на URL-адрес фотографии прически, а div имеет атрибут class для применения к нему стилей card.

Настройка содержания элемента с помощью innerHTML

innerHTML позволяет вам установить или переопределить содержимое вызываемого элемента.

a.innerHTML = "Flat-Twist With Twist Out"

Результирующий HTML

<body>
<h3>Natural Hairstyles Website</h3>
   <div>
      <h4>
        <a>Flat-Twist With Twist Out</a>
      </h4>
      <img />
   </div>
</body>

Установка атрибутов элемента с помощью setAttribute

setAttribute - это функция, которая принимает два параметра: 1) имя устанавливаемого атрибута и 2) значение для установки атрибута.

div.setAttribute('class', 'card')
a.setAttribute('href', 'https://therighthairstyles.com/20-most-inspiring-natural-hairstyles-for-short-hair/')
img.setAttribute('src', 'https://i0.wp.com/therighthairstyles.com/wp-content/uploads/2014/03/13-flat-twist-with-twist-out-2.jpg?w=500&ssl=1')

Результирующий HTML

<body>
  <h3>Natural Hairstyles Website</h3>
  <div class="card">
    <h4>
        <a href="https://therighthairstyles.com/20-most-inspiring-  natural-hairstyles-for-short-hair/">
    Flat-Twist With Twist Out
       </a>
   </h4>
   <img src="https://i0.wp.com/therighthairstyles.com/wp-content/uploads/2014/03/13-flat-twist-with-twist-out-2.jpg?w=500&ssl=1"/>
 </div>
</body>

Да, теперь HTML имеет правильную структуру, содержание и атрибуты!

Окончательный код для этого шага: здесь

5) Динамическое добавление информации в элементы HTML с помощью JavaScript

На выходе из последнего шага пользовательский интерфейс выглядит правильно, но обратите внимание, что атрибут href на a и src на img были установлены с помощью жесткого кодирования, как и имя прически. Что произойдет, если URL-адрес для получения дополнительной информации об этой прическе будет обновлен в вашей базе данных? Как насчет того, чтобы изменить название прически или URL изображения? Вам нужно будет взять новое значение из базы данных, скопировать и вставить его в свой JS. Помните, что файл data.js действует как ваша база данных. В реальных приложениях ваш интерфейс должен иметь возможность взаимодействовать с вашей базой данных. Если значение изменяется в данных, ваш интерфейс должен иметь возможность обновляться без явного копирования и вставки изменения. Давайте углубимся в то, как сделать так, чтобы «разговор» между данными и интерфейсом происходил!

Краткий обзор data.js

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

Для начала создайте файл data.js внутри папки src и заполните его следующим содержимым:

Когда этот файл изменяется, вы хотите, чтобы значения, находящиеся в JS, были изменены, чтобы синхронизировать HTML. Во-первых, ваш JS должен знать об этих данных.

Импорт данных в JS

// in index.js
import data from './data.js'

Несколько вещей по синтаксису, приведенному выше:

  1. Импорт всегда должен размещаться в верхней части файла JavaScript до написания любого другого кода.
  2. import something from 'somewhere' - это базовый синтаксис для переноса содержимого файла в другой файл, добавленный в ES6.
  3. Как вы увидите позже, data можно рассматривать как переменную и он равен массиву, найденному в data.js, который содержит 10 объектов, представляющих разные прически.

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

Данные - это массив из 10 объектов, сейчас вы все еще сосредотачиваетесь на отображении одной карточки. Эта карта извлекает информацию из самого первого объекта в массиве. Как создать константу, представляющую первый элемент или прическу в массиве?

const hairstyle = data[0]

Помните, что 1) скобки [index number] используются для извлечения элемента из массива по определенному индексу и 2) этот индекс массива начинается с нуля.

Как бы вы использовали эту константу hairstyle для обновления вашего предыдущего JS для установки содержимого a в качестве имени прически?

a.innerHTML = hairstyle.name

Помните, что . точек используются с объектами. .name ищет свойство name в объекте hairstyle (первый элемент в массиве data) и возвращает значение этого свойства. Это более динамично, чем a.innerHTML = "Flat-Twist With Twist Out", потому что при изменении свойства name в data.js hairstyle.name автоматически обновится, чтобы отразить это изменение. Я рекомендую вам попробовать это, изменив имя этого первого элемента в массиве data.js и посмотрев, что произойдет.

Двигаясь вперед, как бы вы в дальнейшем использовали hairstyle для обновления вашего предыдущего JS для установки атрибута href на a и атрибута src на img?

a.setAttribute('href', hairstyle.info)
img.setAttribute('src', hairstyle.pic)

Итоговый HTML:

<body>
 <h3>Natural Hairstyles Website</h3>
 <div class="card">
   <h4>
        <a href="https://therighthairstyles.com/20-most-inspiring-  natural-hairstyles-for-short-hair/">
    Flat-Twist With Twist Out
       </a>
   </h4>
   <img src="https://i0.wp.com/therighthairstyles.com/wp-content/uploads/2014/03/13-flat-twist-with-twist-out-2.jpg?w=500&ssl=1"/>
 </div>
</body>

Этот HTML такой же, как и раньше, НО теперь вы динамически настраиваете контент и атрибуты для синхронизации с данными, хорошо!

Код последнего шага: здесь

6) Динамическое создание всего списка из 10 причесок

В файле data.js есть 10 объектов прически, но в настоящее время вы показываете только одну карточку. Давайте изменим это так, чтобы на каждую прическу была своя карточка!

Создавайте HTML для каждой прически в Data с помощью ForEach

У массивов есть много методов, которые можно использовать с ними, например push для добавления нового элемента в массив, map для перебора каждого элемента в массиве и возврата нового массива. И еще есть forEach, функция, которая выполняет итерацию по каждому элементу в массиве и вызывает функцию для каждого элемента. Давайте посмотрим на небольшой пример.

const friends = ['Shaggy', 'Fred', 'Daphne', 'Velma']
const sayHi = (friend) => console.log('Hi ' + friend)
friends.forEach(friend => sayHi(friend))

Результат можно найти в консоли (macs: cmd + option + j, windows: Ctrl + Shift + J)

'Hi Shaggy'
'Hi Fred'
'Hi Daphne'
'Hi Velma'

forEach запускает функцию для каждого элемента в массиве.

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

const buildHairstyleCard = (hairstyle) => {
  // Create elements needed to build a card  
  const div = document.createElement('div')
  const h4 = document.createElement('h4')
  const a = document.createElement('a')
  const img = document.createElement('img')
  // Append newly created elements into the DOM
  const body = document.querySelector('body');
  body.append(div)
  h4.append(a)
  div.append(h4)
  div.append(img)
  // Set content and attributes
  a.innerHTML = hairstyle.name
  a.setAttribute('href', hairstyle.info)
  img.setAttribute('src', hairstyle.pic)
  div.setAttribute('class', 'card')
}

Как вы можете использовать buildHairstyleCard и forEach, чтобы создать карту для каждой прически в массиве data?

data.forEach(hairstyle => buildHairstyleCard(hairstyle))

В приведенном выше коде используется стрелочная функция =>, которая была доступна в ES6. Стрелочные функции хороши тем, что они экономят место и могут запоминать свой контекст. Эту же функцию forEach можно записать в ES5 следующим образом:

const buildHairstyleCard = function(hairstyle){
// Create elements needed to build a card  
  const div = document.createElement('div')
  const h4 = document.createElement('h4')
  const a = document.createElement('a')
  const img = document.createElement('img')
// Append newly created elements into the DOM
  const body = document.querySelector('body');
  body.append(div)
  h4.append(a)
  div.append(h4)
  div.append(img)
// Set content and attributes
  a.innerHTML = hairstyle.name
  a.setAttribute('href', hairstyle.info)
  img.setAttribute('src', hairstyle.pic)
  div.setAttribute('class', 'card')
}

А для forEach:

data.forEach(function(hairstyle) {
  buildHairstyleCard(hairstyle)
}

Код эквивалентен, так что выбирайте!

Окончательный код этого шага и руководства: здесь

Заключение

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

Удачного кодирования!