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