Анализ приложения React.

Эта статья является частью серии (начиная с React By Example: Part 1) статей, в которых с помощью ряда все более сложных примеров исследуется React Библиотека JavaScript. Примеры доступны в виде репозитория GitHub.

В этой статье мы разберем пример приложения React, созданного с помощью Create React App (CRA).

Конфигурация GIT

Файл README.md представляет собой документацию в формате markdown, которая предоставляет копию главной страницы репозитория GIT.

Скрытый файл .gitignore используется системой управления версиями GIT; указывает, какие файлы не отслеживать.

.gitignore

# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

Управление пакетами

Каталог node_modules и два файла package.json и yarn.lock используются для управления пакетами Node.js.

Сотни файлов в node_modules - это все пакеты Node.js, от которых зависит CRA; некоторые из них включаются в окончательный результат (например, React), но большинство из них используется в процессе сборки.

Хотя yarn.lock не предназначен для чтения человеком, package.json:

package.json

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "react-scripts": "1.0.6"
  },
  "dependencies": {
    "react": "^15.5.4",
    "react-dom": "^15.5.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

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

примечание: сотни пакетов в node_modules возникают из каскадного дерева зависимостей.

Раздел сценариев определяет команды, например, начало пряжи и сборка пряжи, которые можно использовать с этим проектом. Если вам интересно, response-scripts - это сценарий, определенный в специальной папке node_modules / .bin

Общедоступно

Файлы в общедоступной папке копируются (с добавленным в них содержимым) в выходную папку build.

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

manifest.json для меня впервые - это необязательный файл, используемый с устройствами Android; не собираюсь обсуждать в этой серии.

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

public / index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

Особое значение имеет строка ‹div id =” root ”› ‹/div› в index.html; React отображает всю DOM внутри этого div; при разработке приложения React нам никогда не нужно отдельно редактировать какие-либо HTML-файлы. Это подводит нас к одному из преимуществ приложения React по сравнению с нашим эталонным приложением.

Хотя исторически это считалось хорошей идеей, разделение задач, необходимость поддерживать HTML и JavaScript в отдельных файлах, является частым источником проблем. Например, в нашем эталонном приложении счетчик строк и приращение должны быть одинаковыми в обоих файлах (источник опечаток).

Сборка

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

Файлы asset-manifest.json и service-worker.js используются для оптимизации работы в автономном режиме (ничего общего с React) и как такие не буду их дальше обсуждать.

Файлы favicon.ico и manifest.json были скопированы из общей папки, которую мы обсуждали ранее.

Файл index.html был скопирован из общего доступа со ссылками на файлы CSS и JavaScript.

Файлы в static / css - это файл CSS и его исходная карта (используется для упрощения отладки).

Аналогичным образом файлы в static / js - это файл JavaScript и его исходная карта.

Наконец, файлы в static / media - это изображения и т. Д., Которые были импортированы в наше приложение (и были слишком большими для преобразования в URL-адреса данных).

Исходный код (знакомство с JSX)

Папка src - это то место, на котором мы сосредоточим наше внимание в оставшейся части этой серии; именно здесь мы храним исходный код, который в конечном итоге включается в готовое к развертыванию приложение в папке build.

Сначала мы проигнорируем как src / registerServiceWorker.js (сервисные работники), так и src / App.test.js (тестирование), поскольку ни один из них не является React специфический (и совершенно необязательный).

index.css и App.css - это просто файлы CSS, которые импортируются в приложение.

src / index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

Наблюдения

  • Поскольку в предыдущих статьях мы потратили время на процесс сборки, все операторы import должны быть вам знакомы.
  • Пока мы их оставим, мы проигнорируем строки registerServiceWorker; мы могли бы легко удалить их без значительного воздействия.
  • Как и в нашем справочном примере, document.getElementById (‘root’) просто возвращает элемент DOM с идентификатором root.
  • Запись ‹App /› называется JSX; это просто сокращение реального кода JavaScript: React.createElement (App, null, null)
  • Расширяя JSX, мы теперь можем понять, почему нам нужно импортировать и React, и App.

Ключевой функцией строки, начинающейся с ReactDOM, является создание экземпляра объекта App (называемого компонентом), а также принятие любого визуализированного HTML-кода, который он генерирует, и вставка его в Объект DOM с идентификатором root. Это очень похоже на то, что мы сделали с innerHTML в нашем справочном примере.

src / App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}
export default App;

Наблюдения

  • Опять же, синтаксис импорта, экспорта и деструктуризации должен быть вам знаком.
  • Синтаксис класса - это функция JavaScript ES2015; в этом случае мы создаем новый класс App, который расширяет (функциональность) Component, предоставляя метод render.
  • То, что выглядит как HTML, на самом деле является сокращением JSX, например, обратите внимание на использование className вместо class (зарезервированное слово в JavaScript).
  • Разница (использование фигурных скобок) между {logo} и «logo» заключается в том, что первый передает свое содержимое как JavaScript (в данном случае переменная logo ), а другой просто передает строку 'logo'.

эквивалентная часть src / App.js

...
React.createElement(
  'div',
  { className: 'App' },
  React.createElement(
    'div',
    { className: 'App-header' },
    React.createElement(
      'img', 
      { 
        src: logo,
        className: 'App-logo',
        alt: 'logo'
      },
      null  
    ),
    React.createElement(
      'h2',
      null,
      'Welcome to React'
    )
  ),
  React.createElement(
    'p',
    { className: 'App-intro' },
    'To get started, edit ',
    React.createElement(
      'code',
      null,
      'src/App.js'
    ),
    ' and save to reload.'
  )
)
...

Если вы написали vanillaJS (без использования библиотек) JavaScript, вы бы использовали комбинацию следующих команд манипулирования DOM для выполнения того, что делает JSX:

  • document.createElement: функция, которая создает элемент DOM.
  • setAttribute: метод элемента DOM для установки атрибута
  • classList.add: свойство элемента DOM и его метод добавления класса.
  • appendChild: метод элемента DOM для добавления дочернего элемента.

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

Следующая часть

В следующей части, React by Example: Part 5, мы повторно реализуем наше приложение-счетчик с React и представим несколько новых концепций React: state и обработка событий.