1. 程式人生 > 遊戲攻略 >《永劫無間》身法教學 大神之路第二期

《永劫無間》身法教學 大神之路第二期

基本概念

Context是react中為了避免在不同層級元件中逐層傳遞props的產物,在沒有Context的時候父元件向子元件傳遞props屬性只能在元件樹上自上而下進行傳遞,但是有些屬性並不是元件樹的每層節點都有相同的需求,這樣我們再這樣逐層傳遞props就顯得程式碼很繁瑣笨重。

使用react.createContext(defulData)可以通過建立一個ContextObject,在某個元件中呼叫ContextObject.Provider同時可以設定新的value = newData覆蓋掉defulData共享到下面的所有子元件,需要ContextObject共享出來的資料的子元件可以通過static contextType = ContextObject接收到data,使用this.context即可呼叫data

適用場景

很多不同層級的元件需要訪問同樣的資料,所以如果我們只是想避免層層傳遞一些屬性,那麼我們還有更好的選擇:組合元件


Context API 理解與運用

React.createContext(defaultValue)
建立一個Context物件,defaultValue是預設引數,在一個元件中可以呼叫這個物件的ProviderAPI,並且設定新的引數:

const Context = React.createContext(defaultValue) function ContextProvider () { return ( <Context.Provider value = { newValue }> /* 子元件(這裡的元件及其子元件都可以收到這個Context物件發出的newValue) */ <Context.Provider/> ) }

但是如果沒有對應的Context.Provider相匹配,那麼元件樹上的所有元件都可以收到這個Context物件發出 的defaultValue;

同時可以呼叫Context的ConsumerAPI可以用來接受到Context的值,並且根據這個值渲染元件:

function ContextConsumer () { return ( <Context.Comsumer> {value => <div> /* 可以根據value進行渲染 */ </div
> } </Context.Comsumer> ) }

Context.Provider & Context.Comsumer

<MyContext.Provider value={variableValue }>可以允許消費元件訂閱到variableValue值的變化,也就是說消費元件可以根據variableValue值的變化而變化,variableValue的值我們可以定義一個事件來控制改變;

<MyContext.Consumer> {value => /* 基於 context 值進行渲染*/} </MyContext.Consumer>

利用Context.ConsumerAPI 可以讓我們即使是在函式式元件也可以訂閱到 Context的值;

這種方法需要一個函式作為子元素,函式接收當前的context值,並返回一個 React 節點。

傳遞給函式的value值等價於元件樹上方離這個 context 最近的 Provider 提供的variableValue值。如果沒有對應的 Provider,value引數等同於傳遞給createContext()的defaultValue。

// Provider 結合 Consumer 使用示例 import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; // 建立 Context 物件 const MyContext = React.createContext(0) // defaultValue 是數字0 // App元件 渲染 Context 物件 class App extends React.Component { constructor(props){ super(props); this.state = { variableValue : 0 } // 處理 Provider中value變化的函式 this.handleChange = () => { this.setState(state => ({ variableValue: state.variableValue + 1 }) ) } } render(){ return ( // 呼叫 Context.Provider, 設定可以讓Consumer元件監聽變化的 value 值 <MyContext.Provider value = {this.state.variableValue}> <Context changeValue = {this.handleChange}/> </MyContext.Provider> ) } } // 消費元件 class Context extends React.Component{ render(){ return ( <MyContext.Consumer> /* 根據Context的value進行渲染 */ {value => <button onClick={this.props.changeValue} > Add MyValue:{value} </button> } </MyContext.Consumer> ) } } ReactDOM.render( <App className = 'app'/> , document.getElementById('root') );

當Provider的variableValue值發生變化時,它內部的所有消費元件都會重新渲染。

Class.contextType

class MyClass extends React.Component { render() { let value = this.context; // this.context 可以訪問到 MyClass 的contextType /* 基於 MyContext 元件的值進行渲染 */ } } MyClass.contextType = MyContext; //將MyClass的contextType屬性賦值為 Context 物件的值

掛載在 class 上的contextType屬性會被重賦值為一個由React.createContext()建立的 Context 物件。此屬效能讓你使用this.context來消費最近 Context 上的那個值。你可以在任何生命週期中訪問到它,包括 render 函式中。

注: 從文件的字面意思,Class.contextType是類元件特有的API,所以函式式元件只能使用Context.Consumer來訪問Context物件的值,我們可以來試一下類元件和函式式元件的API:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// 建立 Context 物件
const MyContext = React.createContext(0)
// App元件 渲染 Context 物件
class App extends React.Component {
constructor(props){
super(props);
this.state = {
variableValue : 0
}
this.handleChange = () => {
this.setState(state => ({
variableValue: state.variableValue + 1
})
)
}
}
render(){
return (
// 呼叫 Context.Provider, 設定可以讓Consumer元件監聽變化的 value 值
<MyContext.Provider value = {this.state.variableValue}>
<Context_consumer changeValue = {this.handleChange} />
<br/>
<Context_contextType changeValue = {this.handleChange} />
<br />
<Func_Consumer changeValue = {this.handleChange} />
<br />
<func_contextType changeValue = {this.handleChange} />
</MyContext.Provider>
)
}
}
// Class & Consumer 消費元件
class Context_consumer extends React.Component{
render(){
return (
<MyContext.Consumer>
{value =>
<button onClick={this.props.changeValue} >
Add Class_consumer:{value}
</button>
}
</MyContext.Consumer>
)
}
}
// Class & contextType 的消費元件
class Context_contextType extends React.Component{
render(){
let value = this.context
return (
<button onClick={this.props.changeValue} >
Add Class_contextType:{value}
</button>
)
}
};
Context_contextType.contextType = MyContext;
// 函式元件 & Consumer
function Func_Consumer (props) {
return (
<MyContext.Consumer>
{value =>
<button onClick={props.changeValue} >
Add Func_consumer:{value}
</button>
}
</MyContext.Consumer>
)
}

// 函式元件 & contextType
function func_contextType (props) {
let value = this.context
return (
<button onClick={props.changeValue} >
Add func_contextType:{value}
</button>
)
}
func_contextType.contextType = MyContext;

ReactDOM.render(
<App className = 'app'/>
,
document.getElementById('root')
);

執行結果:
除了func_contextType元件之外其他元件都可以正常執行

http://www.ssnd.com.cn 化妝品OEM代加工

Context.displayName

context 物件接受一個名為displayName的 property,型別為字串。React DevTools 使用該字串來確定 context 要顯示的內容。

示例,下述元件在 DevTools 中將顯示為 MyDisplayName:

const MyContext = React.createContext(/* some value */); MyContext.displayName = 'MyDisplayName'; <MyContext.Provider> // "MyDisplayName.Provider" 在 DevTools 中 <MyContext.Consumer> // "MyDisplayName.Consumer" 在 DevTools 中