你可能不知道的React用法🔥

前言

React做为前端最🔥的框架之一,可是有的时候咱们仅限于能用的阶段,有一些高级用法,咱们在平常开发中却不多涉足。可是一旦用起来,咱们就能发现它的方便和强大之处,咱们就会愈来愈发现咱们已经离不开它了!这就像是刚用React时,我心里是拒绝的,可是如今我已经离不开它了,愈来愈不能理解之前本身为何抱着JQuery不放呢!javascript

今天咱们重点讲一下Context这个高级API,以及如何封装它,让它更加易用!前端

Context简介

Context 经过组件树提供了一个传递数据的方法,从而避免了在每个层级手动的传递 props 属性。java

在一个典型的 React 应用中,数据是经过props属性由上向下(由父及子)的进行传递的,但这对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI主题),这是应用程序中许多组件都所须要的。 Context 提供了一种在组件之间共享此类值的方式,而没必要经过组件树的每一个层级显式地传递 props 。react

简单说就是,当你不想在组件树中经过逐层传递props或者state的方式来传递数据时,可使用Context来实现跨层级的组件数据传递。markdown

假设咱们有一种场景,咱们有一个业务容器App,里面有一个组件容器Container,Container组件内包含一个Form表单,Form表单里面有一个提交按钮SubmitButton。假如使用props传递,咱们就不得不传递四层。框架

看到了吗?很方便吧!这里咱们使用Context,在组件能够直接经过context获取最顶层绑定的值,避免了一层层传递props的麻烦,也减小出错的可能性。ide

如何使用Context

若是要Context发挥做用,须要用到两种组件,一个是Context生产者(Provider),一般是一个父节点,另外是一个Context的消费者(Consumer),一般是一个或者多个子节点。因此Context的使用基于生产者消费者模式。工具

Context 设计目的是为共享那些被认为对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。例如,在下面的代码中,咱们经过一个“theme”属性手动调整一个按钮组件的样式,使用context,咱们能够避免经过中间元素传递props。this

// 建立一个 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工程师是无所不能的!!!spa

首先是咱们的provider.js,这个就是咱们封装的context使用工具

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组件,每一个组件都有一个独立的文件。

先看入口文件,咱们在入口文件进行绑定上下文,使用provider里面的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>
        )
    }
}
复制代码

Parent组件没什么特殊的

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

class Index extends PureComponent {
    render () {
        return (
            <Son /> ) } } 复制代码

Son组件是真正使用属性propA和propB的地方,咱们经过ES6的Decorator实现,很是方便。注入后,能够像props同样使用。

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>
        )
    }
}
复制代码

后记

在这一小节中,咱们主要讲了React的一个高级语法Context,并且为了使用方便,咱们封装了ContextProvider类和injextContext方法,使用时利用ES6的Decorator语法糖,很是简便。你们在平常开发中,也能够封装出一些这样的小工具,能够极大提高开发效率。

最后元旦快到了,祝你们新年快乐!!!

@Author: WaterMan

相关文章
相关标签/搜索