Некоторые мысли об инкапсуляции реагирующих компонентов

React.js

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

1. Что такое компонент

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

Так называемые компоненты — это инкапсулированные компоненты пользовательского интерфейса с независимыми функциями.

В React все является компонентом, поэтому важно понимать рабочий процесс и суть компонентов.

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

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

  1. Компонуемый: компонент легко использовать с другими компонентами или вкладывать в другой компонент. Если другой компонент создается внутри компонента, то родительский компонент владеет созданными им дочерними компонентами.Благодаря этой функции сложный пользовательский интерфейс можно разделить на несколько простых компонентов пользовательского интерфейса;
  2. Возможность многократного использования: у каждого компонента есть независимые функции, и его можно использовать в нескольких сценариях пользовательского интерфейса;
  3. Сопровождаемый: каждый небольшой компонент содержит только свою собственную логику, которую легче понять и поддерживать;

2. Какими характеристиками должен обладать хорошо спроектированный компонент?

(1) Высокая сплоченность и низкая связанность

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

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

  1. Высокая связность: поместите логически тесно связанный контент в компонент.
    React может сочетать JSX, отображающий содержимое, код JavaScript, определяющий поведение, и даже CSS, определяющий стиль.
    Все они могут быть помещены в один файл JavaScript, поэтому React по своей природе очень связан.
  2. Низкая связанность: зависимости между различными компонентами должны быть максимально ослаблены.
    То есть каждый компонент должен быть максимально независимым.
    Компонент не должен содержать информацию о других компонентах,
    Вместо этого постарайтесь мало или совсем ничего не знать о других компонентах.

Зачем нужно внедрять низкую связанность?

Потому что низкое сцепление принесет следующие преимущества:

  1. Локальные изменения в системе не влияют на другие места
  2. Любой компонент можно заменить заменителем
  3. Компоненты могут быть повторно использованы между системами
  4. Независимые компоненты можно легко тестировать, улучшая охват тестового кода приложения.

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

(2) Скрыть внутреннюю структуру

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

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

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

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

(3) Единая ответственность

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

3. О чем следует подумать в первую очередь при упаковке компонента?

  1. что этот компонент должен делать
  2. Этот компонент должен как минимум знать эту информацию
  3. Что будет возвращать этот компонент?

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

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

(1) Что делает этот компонент:

  1. Может отображать несколько изображений
  2. Вы можете листать страницы слева направо, или вы можете листать страницы вверх и вниз
  3. Состояние PageControl будет меняться в зависимости от прокрутки изображения. Также могут быть некоторые скрытые требования, например:
  4. Должен поддерживать бесконечную прокрутку цикла слева и справа или вверх и вниз
  5. Можно выбрать, вращать ли автоматически
  6. Поддержка ручного скольжения для переключения изображений
  7. У изображения есть событие клика, по которому можно щелкнуть, чтобы выполнить ответ на связанное событие.

(2) Какую информацию должен знать хотя бы этот компонент?

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

  1. Массив URL-адресов изображений
  2. Изображение-заполнитель, когда изображение не существует

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

  1. Включить ли автоматическое вращение, по умолчанию включено или отключено

  2. Независимо от того, прокручивается ли изображение влево и вправо или вверх и вниз, по умолчанию влево и вправо

    так далее ................................................. ....

(3) Что ответит этот компонент?

Доступный эффект карусели

В-четвертых, связь компонентов

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

В качестве входных данных компонента значение реквизита предпочтительно должно быть базового типа js (например, строка, число, логическое значение).
Но реквизит может проходить не только это, это волшебная вещь, он может проходить в том числе:

  1. основные типы js (такие как строка, число, логическое значение)
<Message text="Hello world!" modal={false} />;  
  1. объект
<Message
  data={{ 
  thexAxis:  thexAxis ,     
  lineData : lineData
   }} 
  />
  1. множество
<MoviesList items={['Batman Begins', 'Blade Runner']} />  
  1. В качестве обработчиков событий и асинхронных операций его можно указать как функцию:
<Message type="text" onChange={handleChange} />  
  1. Свойство может быть даже конструктором компонента. Компоненты могут использоваться для обработки экземпляров других компонентов:
function If({ Component, condition }) {  
 return condition ? <Component /> : null;
  }
<If condition={false} component={LazyComponent} />  

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

Доступ к глобальным переменным — еще одна проблема, негативно влияющая на инкапсуляцию.

Мы можем ограничить тип входящих данных через proptypes.

В-пятых, метод создания компонентов в реакции

Существует три способа создания компонентов в React:

  1. функциональные компоненты без сохранения состояния
  2. es5 способ компонента React.createClass
  3. Способ es6 расширяет React.Component

В настоящее время React рекомендует метод ES5 и метод создания компонентов ES6, а также рекомендуется метод написания ES6, поэтому метод написания ES5 здесь обсуждаться не будет.

React.Component

React.Component — это способ создания компонентов React в форме ES6, а также способ, которым React официально рекомендует создавать компоненты.
Как и компоненты, созданные React.createClass, он также создает компоненты с отслеживанием состояния.

По сравнению с React.createClass, React.Component содержит множество улучшений синтаксиса.

1.import

ES6 использует метод import для замены метода require ES5 для импорта модулей, где import { } может напрямую импортировать имена переменных из модуля, что является более кратким и интуитивно понятным.

2. Инициализировать состояние

В правилах синтаксиса ES6 компоненты React используют метод наследования класса для реализации, а функция ловушки getInitialState ES5 удалена, а инициализация состояния объявлена ​​в конструкторе конструктора.

Цитируемое содержание:

Как правильно определить состояние

React рассматривает компонент как конечный автомат. Благодаря взаимодействию с пользователем достигаются различные состояния, а затем визуализируется пользовательский интерфейс для обеспечения согласованности пользовательского интерфейса и данных. Любое изменение пользовательского интерфейса компонента может быть отражено изменением состояния; Все состояния в State используются для отражения изменений в пользовательском интерфейсе, и избыточных состояний быть не должно.

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

  1. Переменные, которые можно получить из родительских компонентов через свойства, не должны использоваться в качестве состояния компонента.
  2. Эту переменную не следует использовать в качестве состояния компонента, если она остается неизменной на протяжении всего срока службы компонента.
  3. Переменные, вычисляемые из других состояний (State) или свойств (Props), не должны использоваться в качестве State компонента.
  4. Переменная, которая не используется в методе рендеринга компонента, не используется для рендеринга пользовательского интерфейса, поэтому эту переменную не следует использовать в качестве состояния компонента. В этом случае переменную лучше определить как обычное свойство компонента.

Разница между функцией и классом для создания компонентов

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

//function方式定义
function Example() {
  return <div>this is a div</div>;
}

const node = Example(props);

// 类方式定义
class Example extends React.Component {
  render() {
    return <div>this is a div</div>;
  }
}

const instance = new Example(props);
const node = instance.render();

Здесь функция вызывается напрямую, и перед вызовом метода рендеринга для созданного объекта необходимо создать экземпляр класса;

Если класс вызывается как обычная функция, будет сообщено об ошибке

Шесть, компонент и чистый компонент

Поскольку я не узнал об этом подробно, я просто кратко суммирую различия:

Помимо предоставления метода shouldComponentUpdate с поверхностными сравнениями, PureComponent
PureComponent и Component в основном идентичны.
При обновлении компонента, если реквизиты и состояние компонента не изменились, метод рендеринга не будет запущен, что сохраняет процесс генерации и сравнения виртуального DOM и достигает цели повышения производительности.

Если мы хотим использовать PureComponent для замены Component, нам не нужно делать слишком много,
Просто измените компонент на PureComponent. Но мы не можем использовать PureComponent для замены Component везде,
Конкретный выбор должен основываться на реальной ситуации, потому что понимание неглубокое, поэтому я не буду подробно обсуждать это здесь.

Семь, компоненты с состоянием и компоненты без состояния

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

    var Header = (props) = (
        <div>{props.xxx}</div>
   );

Компоненты с отслеживанием состояния обычно используются для определения логики взаимодействия и бизнес-данных.
(использовать{this.state.xxx} Выражение монтирует бизнес-данные в экземпляр компонента-контейнера (компонент с состоянием также можно назвать компонентом-контейнером, а компонент без состояния также можно назвать компонентом отображения),
Затем передайте реквизиты компоненту презентации, компонент презентации получает реквизиты и вставляет реквизиты в шаблон.
Похожий на:

class Home extends React.Component {
  constructor(props) {
      super(props);
      };
   render() {
      return (
         <Header/> 
      )
   }
}

Восемь высокоуровневых компонентов

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