這個是從零開始開發一個 React 系列的第七篇。想要訪問以前的內容能夠點擊下方的連接進行訪問:html
增長 Class 的支持git
增長 JSX 的支持github
增長聲明週期api
學習這個課程以前呢,須要各位瞭解 React 的 api,以及作了什麼事情。ide
若是徹底不瞭解的話,不建議您繼續往下看。學習
若是你已經具有了相關 React 的知識,那麼就讓咱們開始吧。ui
本章主要實現 react 的 Context API。
Context 提供了一個無需爲每層組件手動添加 props,就能在組件樹間進行數據傳遞的方法。
在一個典型的 React 應用中,數據是經過 props 屬性自上而下(由父及子)進行傳遞的,但這種作法對於某些類型的屬性而言是極其繁瑣的(例如:地區偏好,UI 主題),這些屬性是應用程序中許多組件都須要的。Context 提供了一種在組件之間共享此類值的方式,而沒必要顯式地經過組件樹的逐層傳遞 props。
咱們繼續拿官網的一個關於Context基礎API的例子來作。
咱們須要將theme從頂層的APP組件傳遞到最下層的Button,從而Button可以根據主題的不一樣顯示不一樣的樣式,不使用Context的話是這樣的:
使用Context的話是這樣的:
代碼以下:
// Context 可讓咱們無須明確地傳遍每個組件,就能將值深刻傳遞進組件樹。
// 爲當前的 theme 建立一個 context(「light」爲默認值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// 使用一個 Provider 來將當前的 theme 傳遞給如下的組件樹。
// 不管多深,任何組件都能讀取這個值。
// 在這個例子中,咱們將 「dark」 做爲當前的值傳遞下去。
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// 中間的組件不再必指明往下傳遞 theme 了。
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
// 指定 contextType 讀取當前的 theme context。
// React 會往上找到最近的 theme Provider,而後使用它的值。
// 在這個例子中,當前的 theme 值爲 「dark」。
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
複製代碼
經過代碼發現這裏一共須要實現的API有React.createContext
, 還有一個contextType
.其中React.createContext
是會返回一個對象。這個對象有一個key爲Provider的組件。 這個組件接受一個value的prop並將其做爲context的值。 contextType是一個靜態屬性,也就說全部的組件實例都公用一個,不必都產生一個。咱們的組件從Context裏讀取最新的數據便可。
接下來咱們分別實現React.createContext
和contextType
。
咱們首先要作的第一件事情就是導出createContextAPI, 儘管這個API咱們還沒寫,咱們先佔個位置。
const React = {
createElement,
Component: require("./component"),
+ createContext: require("./context").createContext
};
複製代碼
咱們新建一個文件context.js
咱們先放一個空殼子進去,接下來咱們就要實現這個,其實代碼很簡單。
+ import React from './mini-react';
+ import Component from './component';
+ export function createContext(defaultValue) {
+ return {
+ Provider: class Provider extends Component {
+ render() {
+ return <div></div>
+ }
+ }
+ }
+}
複製代碼
接下來咱們填充具體的邏輯,邏輯很簡單,直接上代碼。
import React from './mini-react';
import Component from './component';
export function createContext(defaultValue) {
return {
Provider: class Provider extends Component {
render() {
+ const currentValue = this.props.value;
+ Provider.currentValue = currentValue || defaultValue;
return <div></div>
}
}
}
}
複製代碼
兩行代碼搞定了context數據的更新邏輯,如何讓全部組件都能接受到裏面的值呢? 接下來咱們須要修改下Component
的實現。
簡單增長一行代碼:
class Component {
constructor(props) {
this.props = props;
+ this.context = this.constructor.contextType && this.constructor.contextType.Provider.currentValue;
...
}
...
}
複製代碼
本節實現了React的Context API相關的功能, 下一節咱們引入Ref(文章未更新)