摘要:和是成對出現(xiàn)的,每一個都會對應(yīng)一個。而每一對都是由創(chuàng)建出來的。是一個普通的組件,當(dāng)然,是需要位于組件的上層。又聲明了這個范圍的數(shù)據(jù)結(jié)構(gòu)。解決嵌套問題的方式也更優(yōu)雅。即使這一對的于另一對的的數(shù)據(jù)結(jié)構(gòu)和值的類型相同,這個也讓能訪問那個的上下文。
我們都知道,基于props做組件的跨層級數(shù)據(jù)傳遞是非常困難并且麻煩的,中間層組件要為了傳遞數(shù)據(jù)添加一些無用的props。
而React自身早已提供了context API來解決這種問題,但是16.3.0之前官方都建議不要使用,認為會遲早會被廢棄掉。說歸說,很多庫已經(jīng)采用了
context API。可見呼聲由多么強烈。終于在16.3.0之后的版本,React正式提供了穩(wěn)定的context API,本文中的示例基于v16.3.0之后的context API。
首先要理解上下文(context)的作用以及提供者和消費者分別是什么,同時要思考這種模式解決的是什么問題(跨層級組件通信)。
context做的事情就是創(chuàng)建一個上下文對象,并且對外暴露提供者(通常在組件樹中上層的位置)和消費者,在上下文之內(nèi)的所有子組件,
都可以訪問這個上下文環(huán)境之內(nèi)的數(shù)據(jù),并且不用通過props。可以理解為有一個集中管理state的對象,并限定了這個對象可訪問的范圍,
在范圍之內(nèi)的子組件都能獲取到它內(nèi)部的值。
提供者為消費者提供context之內(nèi)的數(shù)據(jù),消費者獲取提供者為它提供的數(shù)據(jù),自然就解決了上邊的問題。
用法這里要用到一個小例子,功能就是主題顏色的切換。效果如圖:
根據(jù)上邊的概念和功能,分解一下要實現(xiàn)的步驟:
創(chuàng)建一個上下文,來提供給我們提供者和消費者
提供者提供數(shù)據(jù)
消費者獲取數(shù)據(jù)
這里的文件組織是這樣的:
├─context.js // 存放context的文件 │─index.js // 根組件,Provider所在的層級 │─Page.js // 為了體現(xiàn)跨層級通信的添加的一個中間層級組件,子組件為Title和Paragraph │─Title.js // 消費者所在的層級 │─Paragraph.js // 消費者所在的層級創(chuàng)建一個上下文
import React from "react" const ThemeContext = React.createContext() export const ThemeProvider = ThemeContext.Provider export const ThemeConsumer = ThemeContext.Consumer
這里,ThemeContext就是一個被創(chuàng)建出來的上下文,它內(nèi)部包含了兩個屬性,看名字就可以知道,一個是提供者一個是消費者。
Provider和Consumer是成對出現(xiàn)的,每一個Provider都會對應(yīng)一個Consumer。而每一對都是由React.createContext()創(chuàng)建出來的。
沒啥好說的,就是一個容器組件而已
const Page = () => <>提供者提供數(shù)據(jù)>
提供者一般位于比較上邊的層級,ThemeProvider 接受的value就是它要提供的上下文對象。
// index.js import { ThemeProvider } from "./context" render() { const { theme } = this.state return消費者獲取數(shù)據(jù)}
在這里,消費者使用了renderProps模式,Consumer會將上下文的數(shù)據(jù)作為參數(shù)傳入renderProps渲染的函數(shù)之內(nèi),所以這個函數(shù)內(nèi)才可以訪問上下文的數(shù)據(jù)。
// Title.js 和 Paragraph的功能是一樣的,代碼也差不多,所以單放了Title.js import React from "react" import { ThemeConsumer } from "./context" class Title extends React.Component { render() { return關(guān)于嵌套上下文{ theme => } }title
}
此刻你可能會產(chǎn)生疑問,就是應(yīng)用之內(nèi)不可能只會有一個context。那多個context如果發(fā)生嵌套了怎么辦?
v16.3.0之前的版本其實v16.3.0之前版本的React的context的設(shè)計上考慮到了這種場景。只不過實現(xiàn)上麻煩點。來看一下具體用法:
和當(dāng)前版本的用法不同的是,Provider和Consumer不是成對被創(chuàng)建的。
Provider是一個普通的組件,當(dāng)然,是需要位于Consumer組件的上層。要創(chuàng)建它,我們需要用到兩個方法:
getChildContext: 提供自身范圍上下文的數(shù)據(jù)
childContextTypes:聲明自身范圍的上下文的結(jié)構(gòu)
class ThemeProvider extends React.Component { getChildContext() { return { theme: this.props.value }; } render() { return ({this.props.children} ); } } ThemeProvider.childContextTypes = { theme: PropTypes.object };
再看消費者,需要用到contextTypes,來聲明接收的上下文的結(jié)構(gòu)。
const Title = (props, context) => { const {textColor} = context.theme; return (我是標題
); }; Title.contextTypes = { theme: PropTypes.object };
最后的用法:
回到嵌套的問題上,大家看出如何解決的了嗎?
Provider做了兩件事,提供context數(shù)據(jù),然后。又聲明了這個context范圍的數(shù)據(jù)結(jié)構(gòu)。而Consumer呢,通過contextTypes定義接收到的context數(shù)據(jù)結(jié)構(gòu)。
也就相當(dāng)于Consumer指定了要接收哪種結(jié)構(gòu)的數(shù)據(jù),而這種結(jié)構(gòu)的數(shù)據(jù)又是由某個Provider提前定義好的。通過這種方式,再多的嵌套也不怕,Consumer只要定義
接收誰聲明的context的結(jié)構(gòu)就好了。如果不定義的話,是接收不到context的數(shù)據(jù)的。
v16.3.0之后的版本使用起來比以前簡單了很多。解決嵌套問題的方式也更優(yōu)雅。由于Provider和Consumer是成對地被創(chuàng)建出來的。即使這一對的Provider于另一對的
Consumer的數(shù)據(jù)結(jié)構(gòu)和值的類型相同,這個Consumer也讓能訪問那個Provider的上下文。這便是解決方法。
對于這個context這個東西。我感覺還是不要在應(yīng)用里大量使用。就像React-Redux的Provider,或者antd的LocalProvider,差不多用一次就夠,因為用多會使應(yīng)用里很混亂,
組件之間的依賴關(guān)系變得復(fù)雜。但是React為我們提供的這個api還是可以看到它自身還是想彌補其狀態(tài)管理的短板的,況且Hooks中的useReducer出現(xiàn)后,更說明了這一點。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/104502.html
摘要:本篇是深入系列的最后一篇,將介紹開發(fā)應(yīng)用時,經(jīng)常用到的模式,這些模式并非都有官方名稱,所以有些模式的命名并不一定準確,請讀者主要關(guān)注模式的內(nèi)容。 React 深入系列,深入講解了React中的重點概念、特性和模式等,旨在幫助大家加深對React的理解,以及在項目中更加靈活地使用React。 本篇是React深入系列的最后一篇,將介紹開發(fā)React應(yīng)用時,經(jīng)常用到的模式,這些模式并非都有...
摘要:另外一點是組件應(yīng)該盡量保證獨立性,避免和外部的耦合,使用全局事件造成了和外部事件的耦合。明確的職責(zé)分配也增加了應(yīng)用的確定性明確只有組件能夠知道狀態(tài)數(shù)據(jù),且是對應(yīng)部分的數(shù)據(jù)。 書籍完整目錄 4.2 react patterns 修改 Props Immutable data representation 確定性 在 getInitialState 中使用 props 私有狀態(tài)和...
摘要:這一周連續(xù)發(fā)表了兩篇關(guān)于的文章組件復(fù)用那些事兒實現(xiàn)按需加載輪子應(yīng)用設(shè)計之道化妙用其中涉及到組件復(fù)用輪子設(shè)計相關(guān)話題,并配合相關(guān)場景實例進行了分析。 showImg(https://segmentfault.com/img/remote/1460000014482098); 這一周連續(xù)發(fā)表了兩篇關(guān)于 React 的文章: 組件復(fù)用那些事兒 - React 實現(xiàn)按需加載輪子 React ...
摘要:這一周連續(xù)發(fā)表了兩篇關(guān)于的文章組件復(fù)用那些事兒實現(xiàn)按需加載輪子應(yīng)用設(shè)計之道化妙用其中涉及到組件復(fù)用輪子設(shè)計相關(guān)話題,并配合相關(guān)場景實例進行了分析。 showImg(https://segmentfault.com/img/remote/1460000014482098); 這一周連續(xù)發(fā)表了兩篇關(guān)于 React 的文章: 組件復(fù)用那些事兒 - React 實現(xiàn)按需加載輪子 React ...
閱讀 1010·2021-11-22 13:52
閱讀 924·2019-08-30 15:44
閱讀 570·2019-08-30 15:43
閱讀 2424·2019-08-30 12:52
閱讀 3473·2019-08-29 16:16
閱讀 637·2019-08-29 13:05
閱讀 2943·2019-08-26 18:36
閱讀 1975·2019-08-26 13:46