你可能不知道的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

相關文章
相關標籤/搜索