|
一.产生context原因
从父组件直接传值到孙子组件,而不必一层一层的通过props进行传值,相比较以前的那种传值更加的方便、简介。
二.context的实现方式
新版本(React16.x后)
//创建两个组件 Provider,Consumer
//let {Provider,Consumer}=React.createContext(defaultValue); //defaultValue可以设置共享的默认数据 当Provider不存在的时候 defaultValue生效
const { Provider, Consumer } = React.createContext({ theme: "green" })
class MessageList extends React.Component {
render() {
//Procider组件遍历子组件,并且有一个属性value用来提供数据
return (
<Provider value={{ theme: "pink" }}>
<Content />
</Provider>
)
}
}
//中间组件
function Content() {
return (
<div>
<Button />
</div>
)
}
//接收组件,如果子组件是Consumer的话,将value作为参数值,传递给新创建的Consumer渲染一个函数组件
function Button() {
return (
<Consumer>
{({ theme }) => (
<button
style={{ backgroundColor: theme }}>
Toggle Theme
</button>
)}
</Consumer>
)
}
注意:将undefined传递给<Provider>的value时,createContext中的defaultValue不会生效,Consumer的value显示空值
三.React.createContext()源码解析
//calculateChangedBits方法,使用Object.is()计算新老context变化 //defaultValue 当Provider组件属性value不存在时 会使用默认值defaultValue
function createContext(defaultValue, calculateChangedBits) { if (calculateChangedBits === undefined) {
calculateChangedBits = null;
} else {
{
!(calculateChangedBits === null || typeof calculateChangedBits === 'function') ? warningWithoutStack$1(false, 'createContext: Expected the optional second argument to be a ' + 'function. Instead received: %s', calculateChangedBits) : void 0;
}
}
var context = {
$$typeof: REACT_CONTEXT_TYPE, //context的$$typeof在createElement中的type中的type对象中存储
_calculateChangedBits: calculateChangedBits,//计算新老context变化
//_currentValue和_currentValue2作用一样,只是作用平台不同
_currentValue: defaultValue, //Provider的value属性
_currentValue2: defaultValue,
_threadCount: 0, //用来追踪context的并发渲染器数量
// These are circular
Provider: null, //提供组件
Consumer: null //应用组件
};
//context.Provider的_context指向context对象
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context
};
var hasWarnedAboutUsingNestedContextConsumers = false;
var hasWarnedAboutUsingConsumerProvider = false;
{
// A separate object, but proxies back to the original context object for
// backwards compatibility. It has a different $$typeof, so we can properly
// warn for the incorrect usage of Context as a Consumer.
var Consumer = {
$$typeof: REACT_CONTEXT_TYPE,
_context: context,
_calculateChangedBits: context._calculateChangedBits //计算新老context变化
}; // $FlowFixMe: Flow complains about not setting a value, which is intentional here
Object.defineProperties(Consumer, {
Provider: {
get: function () {
if (!hasWarnedAboutUsingConsumerProvider) {
hasWarnedAboutUsingConsumerProvider = true;
warning$1(false, 'Rendering <Context.Consumer.Provider> is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Provider> instead?');
}
return context.Provider;
},
set: function (_Provider) {
context.Provider = _Provider;
}
},
_currentValue: {
get: function () {
return context._currentValue;
},
set: function (_currentValue) {
context._currentValue = _currentValue;
}
},
_currentValue2: {
get: function () {
return context._currentValue2;
},
set: function (_currentValue2) {
context._currentValue2 = _currentValue2;
}
},
_threadCount: {
get: function () {
return context._threadCount;
},
set: function (_threadCount) {
context._threadCount = _threadCount;
}
},
Consumer: {
get: function () {
if (!hasWarnedAboutUsingNestedContextConsumers) {
hasWarnedAboutUsingNestedContextConsumers = true;
warning$1(false, 'Rendering <Context.Consumer.Consumer> is not supported and will be removed in ' + 'a future major release. Did you mean to render <Context.Consumer> instead?');
}
return context.Consumer;
}
}
}); // $FlowFixMe: Flow complains about missing properties because it doesn't understand defineProperty
context.Consumer = Consumer;
}
{
context._currentRenderer = null;
context._currentRenderer2 = null;
}
//返回一个context对象
return context;
}
解析:
1._currentValue 用来记录Provider/Consumer的value值 默认为defaultValue
2.在context设置Provider和Consumer属性值
context.Provider = {
$$typeof: REACT_PROVIDER_TYPE,
_context: context
};
表示给context的provider设置属性值 如果我们需要设置当前Provider上的value值 则直接使用context.Provider._context._currentValue进行设置
var Consumer = {
$$typeof: REACT_CONTEXT_TYPE,
_context: context,
_calculateChangedBits: context._calculateChangedBits
};
context.Consumer = Consumer;
表示给context设置Consumer设置属性值 如果我们需要获取当前通过Provider上的value值 则直接通过自身的Consumer组件的context.Consumer._context._currentValue获取value值
3.return context对象
返回的context对象中包含Provider/Consumer/_currentValue/_calculateChangedBits计算新老context变化等值
const { Provider, Consumer } = React.createContext({ theme: "green" })
通过React.createContext调用createContext方法 获取context中的Provider和Consumer组件对象 当调用React.createElement(type,config,..)作为type值进行传递
返回的context内容图解:
来源:https://www.cnblogs.com/sunxiaopei/p/12319203.html |