Выбор правильного типа компонента для React Advanced

внешний интерфейс JavaScript Vue.js React.js
Выбор правильного типа компонента для React Advanced

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

Оригинальная ссылка:Я 3CT rain.com/2018/11/05/…

Чтобы полностью понять React, сначала поймите, что обычно пишут на JSX. Когда я только учился, я был в замешательстве: это новый язык? Большинство людей начинают разработку, продираясь сквозь документацию. Благодаря обработке babel-presets-react вы можете увидеть, что JSX — это просто синтаксический сахар, и в конце концов JS все еще работает в браузере. Компонент React в конечном итоге создается с помощью React.createElement.Короче говоря, написание React — это на самом деле написание JS..

jsx

SFC (функциональный компонент без сохранения состояния)

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

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Написание с помощью стрелочных функций еще более лаконично.

const Welcome = props => <h1>Hello, {props.name}</h1>;

Вышеупомянутые две формы генерации кода es5 одинаковы.

var Welcome = function Welcome(props) {
  return _react2.default.createElement(
    "h1",
    null,
    "Hello, ",
    props.name
  );
};

Характеристики SFC в том, что он только рендерит, код короткий и других условных ветвей нет, а объем скомпилированного кода будет меньше, чем у класса Component.

К сожалению, в React 16.7react hooksПосле того, как он вышел, название SFC неоднозначно, потому что, используя useState, SFC также может иметь локальное состояние, а также может иметь жизненный цикл. Было бы неловко снова называть его Stateless Components.Изменить название на FC?

HOC (Higher-Order Components)

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

function logProps(WrappedComponent) {
  return class extends React.Component {
    componentWillReceiveProps(nextProps) {
      console.log('Current props: ', this.props);
      console.log('Next props: ', nextProps);
    }
    render() {
      return <WrappedComponent {...this.props} />;
    }
  }
}

Наиболее распространенным компонентом более высокого порядка является метод connect в react-redux, который подключает компонент к хранилищу, передавая компонент и метод map*ToProps. Значение после подключения можно получить напрямую через пропсы внутри компонента.

exprot default connect(
  mapStateToProps,
  mapDispatchToProps,
)(Component);

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

Dynamic Component

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

// Heading.js
render() {
    const { tag: Tag, children } = this.props;
    return <Tag>{ children }</Tag>
}

Согласно теории всего JS, если передаются разные теги, будут отображаться разные теги заголовков.

heading

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

FaCC (функционирует как дочерние компоненты)

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

class LoadArea extends Component {
  state = {
    loading: true,
  };

  componentDidMount() {
    asyncFunc()
        .then(() => {
            this.setState({
              loading: false,
            })
        })
        .catch(() => {
            this.setState({
              loading: false,
            })
        })
  }

  render() {
    return (
      <React.Fragment>
        {this.props.children({
          ...this.props,
          ...this.state,
        })}
      </React.Fragment>
    );
  }
}

Применение

render() {
    <LoadingArea>
        ({ loading }) => {
            loading
                ? <Wating />
                : <Main />
        }
    </LoadingArea>
}

Опять же, неудивительно, что окончательное выполнение полностью выполняется на JS.

React 16.* Новая версия Conext.Consumer написана таким образом.

render() {
    <ThemeContext.Provider value={this.state.theme}>
      ...
        <ThemeContext.Consumer>
          {({theme}) => (
            <button
              style={{backgroundColor: theme.background}}>
              Toggle Theme
            </button>
          )}
        </ThemeContext.Consumer>
      ...
    </ThemeContext.Provider>    
}

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

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

Сплит компонента:

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

Поддельный код:

// CountDownContainer.js
render() {
    const {
      endTime,
      renderSomethingAfterCountDown,
    } = this.props;

    return (
      <TimeLeftProvider endTime={endTime} >
        {seconds => (
          seconds > 0
            ? <CountDown {...this.props} remainingSeconds={seconds} />
            : renderSomethingAfterCountDown()
        )}
      </TimeLeftProvider>
    );
}
// TimeLeftProvider.js
export default class TimeLeftProvider extends PureComponent {
  static propTypes = {
    children: PropTypes.func,
    endTime: PropTypes.number,
  }

  // ...

  componentDidMount() {
    this.poll();
  }

  poll() {
    queryServerTime();
    this.pollTimer = setInterval(() => {
      queryServerTime();
    }, pollInterval * 1000);
  }

  countDown() {
    setInterval(() => {
      this.setState(prevState => ({
        remainingSeconds: prevState.remainingSeconds - 1,
      }));
    }, 1000);
  }

  render() {
    const { remainingSeconds, reliable } = this.state;
    return this.props.children(remainingSeconds, reliable);
  }
}
// CountDown.js

function CountDown(props) {
    const {
      remainingSeconds,
    } = props;
    const numbers = formatSeconds(remainingSeconds);
    const inputs = ['days', 'hours', 'minutes', 'seconds'];

    return (
      <div styleName={cls}>
        {
          inputs.map(key => ({
            label: key,
            number: numbers[key],
          })).map(
             //...
          )
        }
      </div>
    );
}

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

Count Down

в то же время

  • Структура кода понятна, и каждый компонент выполняет свою роль.
  • Компоненты можно использовать повторно.
  • Юнит-тестирование простое, каждый компонент тестирует только свою логику.

Рекомендуемое чтение