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

Недавно я сделал YouTube-видео о компонентах Sub Rendering React, которое было основано на сообщении в блоге, которое я написал здесь. Какой-то крутой парень прокомментировал видео, потому что он был крутым, комментируя (намек, подмигнуть, подтолкнуть, подтолкнуть). В любом случае, передайте привет крутому парню, который называет себя Max Equation. Он оставил этот обнадеживающий комментарий, который вдохновил меня на написание этого сообщения в блоге:

Я расскажу об интеграции TypeScript с ReactJS в другой раз. Но в этом посте я хотел бы обратиться к концепции модульного построения функций и классов JavaScript!

Что означает модуляризация в JavaScript?

Что ж, это причудливый, но простой метод, использующий функции import и export, поставляемые с ES6. Я регулярно использую это в своей работе по React, но это то, что можно использовать в любом фреймворке JavaScript.

Чтобы объяснить эту концепцию, нам сначала нужно рассмотреть, как работает импорт и экспорт ES6. Давайте посмотрим на пример простого функционального компонента React без сохранения состояния, который отображает компоненты Header, Content и Footer. Эти компоненты определены в трех отдельных файлах в папке components. Папка components находится на том же уровне каталога, что и наш простой компонент, который мы назовем MyComponent в демонстрационных целях. Вот наша реализация MyComponent:

import React from 'react';
import Header from './components/header;
import Content from './components/content;
import Footer from './components/footer;
const MyComponent = () => (
  <>
    <Header />
    <Content />
    <Footer />
  </>
);
export default MyComponent;

Я хочу сосредоточиться на import разделе этого компонента, чтобы упростить его. Если вы не знакомы с синтаксисом <>...</>, тогда прочтите мой пост о React Fragments.

В этом примере компоненты Header, Content и Footer имеют очень похожую реализацию. Давайте сосредоточимся на компоненте Header. Этот Header компонент является либо экспортируемой функцией по умолчанию в файле в папке components с именем header.js. В противном случае это экспортируемая функция по умолчанию в index.js файле в папке с именем header внутри папки components. Хорошо, это был полный рот… Ты все еще со мной?

Обычно ссылка на './header' - это либо файл header.js, либо файл index.js внутри папки header. Что ж, если вы не поняли сейчас, я не знаю, что еще сказать. Я сделаю видео на YouTube через несколько дней, чтобы попытаться объяснить это. Вы можете подписаться на него по этой ссылке.

Экспорт по умолчанию и экспорт именованной функции / класса

Помните, я сказал, что эти импортированные компоненты являются функциями экспорта по умолчанию для файлов, из которых они были экспортированы? Что ж, давайте посмотрим на файл header.js, чтобы понять, что я имею в виду:

const Header = () => <div>Header</div>;
export default Header;

Мы export default Header;, поэтому, когда мы импортируем его в наш основной компонент, мы импортируем его следующим образом:

import Header from './components/header';

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

const Header = () => <div>Header</div>;
export Header; // See the 'default' keyword is removed

Вы также можете экспортировать его с таким названием:

export const Header = () => <div>Header</div>;

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

import { Header } from './components/header';

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

В чем тогда смысл экспорта именованных функций и классов?

Здесь все становится круто. Представьте, что мы поленились и решили не создавать отдельные файлы для наших Header, Content и Footer компонентов, #screwbestpractices. Что, если бы мы просто экспортировали их все, как указано в index.js файле в нашей папке компонентов, как в этом примере ниже?

export const Header = () => <div>Header</div>;
export const Content = () => <div>Content</div>;
export const Footer = () => <div>Footer</div>;

Что ж, это довольно круто, теперь мы можем импортировать их в наш основной компонент следующим образом:

import { Header, Content, Footer } from './components';

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

const Header = () => <div>Header</div>;
export const Content = () => <div>Content</div>;
export const Footer = () => <div>Footer</div>;
export default Header;

Затем мы импортируем его в наш основной компонент следующим образом:

import Header, { Content, Footer } from './components';

Еще несколько советов по импорту и экспорту:

Последняя вещь. Технически вы можете import экспортировать класс по умолчанию под любым именем. Например, вы можете импортировать то же самое:

import RandomOtherName, { Content, Footer } from './components';

Или вы можете назвать экспорт по умолчанию как-то еще внутри именованного импорта, например:

import { default as Header, Content, Footer } from './components';

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

export const Content = () => <div>Content</div>;
export const Footer = () => <div>Footer</div>;
export default () => <div>Header</div>;

При этом все равно будут работать те методы импорта, о которых я упоминал выше.

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

Модуляризация кода в действии!

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

import Header from './components/header';
import Content from './components/content';
import Footer from './components/footer';

Это правильно, но замечаете ли вы еще одну общепринятую передовую практику, которой мы здесь пренебрегаем? Если вы думаете о слове «СУХОЙ», то вы правы! «СУХОЙ» означает «Не повторяйся». Вы, вероятно, можете увидеть здесь общую закономерность. Мы импортируем несколько функций из одной папки, но они находятся в разных файлах. Мы можем здесь что-нибудь сделать?

Если мы объединим все наши техники с тем, что у нас есть, мы сможем творить удивительные волшебные вещи! Помните, все наши функции находятся в папке components, верно? Что, если оставить все как есть и добавить файл index.js в нашу папку components, чтобы экспортировать все наши функции по умолчанию как именованные функции в одном месте? Отличная идея! И сделать это легко так:

export { default as Header } from './header';
export { default as Content } from './content';
export { default as Footer } from './footer';

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

import { Header, Content, Footer } from './components';

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

Еще одно место, где можно применить эту технику

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

Заключение

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

Мое вдохновение для написания таких сообщений пришло из Code Complete: Практическое руководство по построению программного обеспечения, второе издание. Эта книга стала катализатором роста для многих разработчиков, включая меня. Если у вас нет копии, я настоятельно рекомендую вам сделать себе одолжение и получить ее!

В любом случае! Если вам понравился этот пост, то оставьте лайки и аплодисменты. И если вы хотите быть в курсе других моих материалов, обязательно подпишитесь на меня в Facebook, Twitter, Medium, YouTube и LinkedIn.

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

Первоначально опубликовано на www.barrymichaeldoyle.com 10 сентября 2018 г.