Использование React, о котором вы могли не знать 🔥

React.js

предисловие

React — один из самых популярных фреймворков во внешнем интерфейсе, но иногда мы ограничены этапом, на котором мы можем его использовать, и есть некоторые расширенные области применения, которые мы редко используем в повседневной разработке. Но как только мы его используем, мы можем найти его удобство и силу, и мы будем находить все больше и больше того, что мы не можем жить без него! Это как когда я впервые использовал React, я отвергал его в своем сердце, но теперь я не могу жить без него, и я не могу понять, почему я не отказался от JQuery раньше!

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

Введение в контекст

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

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

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

Предположим, у нас есть сценарий, у нас есть приложение бизнес-контейнера, в котором есть компонент-контейнер Container, компонент Container содержит форму формы, а форма формы имеет кнопку отправки SubmitButton. Если мы используем реквизит для передачи, мы должны пройти четыре слоя.

видеть это? Очень удобно! Здесь мы используем Context, и компонент может напрямую получить связанное значение верхнего уровня через контекст, что позволяет избежать проблем с передачей свойств слой за слоем и снижает вероятность ошибок.

Как использовать контекст

Если вы хотите, чтобы Context функционировал, вам нужно использовать два компонента: один — производитель контекста (поставщик), обычно родительский узел, а другой — потребитель контекста (потребитель), обычно один или несколько дочерних узлов. Таким образом, использование Context основано на модели производитель-потребитель.

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

// 创建一个 theme Context,  默认 theme 的值为 light
const ThemeContext = React.createContext('light');

function ThemedButton(props) {
  // ThemedButton 组件从 context 接收 theme
  return (
    <ThemeContext.Consumer>
      {theme => <Button {...props} theme={theme} />}
    </ThemeContext.Consumer>
  );
}

// 中间组件
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

более простой способ использования

Прочитав описанный выше метод использования, вы все еще чувствуете себя немного некомфортно, есть ли более простой способ или вы можете помочь мне его инкапсулировать? Конечно, Javascript-инженеры всемогущи! ! !

Первый — это provider.js, который является нашим инкапсулированным инструментом использования контекста.

import React, { Component } from 'react';

export const Context = React.createContext();

export class ContextProvider extends Component {
    render() {
        return (
            <Context.Provider value={this.props.context}>
                {this.props.children}
            </Context.Provider>
        );
    }
}

/**
 * 用注解的方式给子组件注入属性
 */

export const injectContext = (contexts) => RealComponent => {
    return class extends Component {
        render() {
            return (
                <Context.Consumer>
                    {context => {
                        // 将顶层的context分发到各层
                        let mapContext = {};
                        if(Array.isArray(contexts)) {
                            contexts.map(item => {
                                mapContext[item] = context[item];
                            });
                        }
                        return (
                            <RealComponent {...mapContext} {...this.props} />
                        )
                    }}
                </Context.Consumer>
            );
        }
    };
};

Позвольте мне дать вам каштан, чтобы все поняли удобство вышеуказанного метода инкапсуляции. Если вы хотите реализовать GrandParent -> Parent -> Son, передайте свойства из компонента GrandParent в компонент GrandSon, каждый компонент имеет отдельный файл.

Сначала посмотрим на файл записи. Мы привязываем контекст в файле записи и используем класс ContextProvider в провайдере. Здесь мы в основном связываем propA и propB.

// 入口文件

import React, { PureComponent } from 'react';
import { ContextProvider } from './provider';
import GrandParent from './GrandParent';

class Index extends PureComponent {
    render () {
        return (
            <ContextProvider context={{
                propA: 'propA',
                propB: 'propB'
            }}>
                <GrandParent />
            </ContextProvider>
        )
    }
}

Родительский компонент ничего особенного

import React, { PureComponent } from 'react';
import Son from './Son';

class Index extends PureComponent {
    render () {
        return (
            <Son />
        )
    }
}

В компоненте Son действительно используются свойства propA и propB.Мы реализуем его через Decorator ES6, что очень удобно. После введения его можно использовать как реквизит.

import React, { PureComponent } from 'react';
import { injectContext } from './provider';
import Son from './Son';

@injextContext(['propA', 'propB'])
class Index extends PureComponent {
    render () {
        return (
            <div>
                <span>propA为{this.props.propA}</span>
                <span>propB为{this.props.propB}</span>
            </div>
        )
    }
}

постскриптум

В этом разделе мы в основном говорим о расширенном синтаксисе Context React, а для удобства использования мы инкапсулируем класс ContextProvider и метод injextContext, а также используем синтаксический сахар Decorator ES6, что очень удобно. В повседневной разработке вы также можете инкапсулировать некоторые такие небольшие инструменты, которые могут значительно повысить эффективность разработки.

Приближается последний Новый год, поздравляю вас с наступающим Новым годом! ! !

@Author: WaterMan