從零開始開發一個 React

這個是從零開始開發一個 React 系列的第七篇。想要訪問以前的內容能夠點擊下方的連接進行訪問:html

  1. 最簡單的實現,包括 vdom 結構,createElement,ReactDOM.renderreact

  2. 增長 Class 的支持git

  3. 增長 JSX 的支持github

  4. 增長 state 支持算法

  5. 增長聲明週期api

  6. 增長 dom-diff(調和算法)dom

先行知識

學習這個課程以前呢,須要各位瞭解 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.createContextcontextType

導出 React.createContext API

咱們首先要作的第一件事情就是導出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(文章未更新)

相關文章
相關標籤/搜索