果果哥 發表於 2019-7-21 16:13:00

React的Context的使用方法简介

<p><strong><span style="font-size: 14pt">context </span></strong></p>
<p><span style="font-size: 18px">定义:&nbsp;Context提供了一种方式,能够让数据在组件树中传递,而不必一级一级手动传递。</span></p>
<p><span style="font-size: 18px">API : createContext(defaultValue?)。</span></p>
<p><strong><span style="font-size: 18px">使用方法:</span></strong></p>
<p><span style="font-size: 18px">首先要引入</span><strong><span style="font-size: 18px">createContext</span></strong></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">import React, { Component, createContext } from 'react';</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px">&nbsp;然后创建一个Context&nbsp;</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">const BatteryContext = createContext();</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px">然后用BatteryContext.Provider包裹组件并且传递属性值。</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">&lt;BatteryContext.Provider value={60}&gt;
   &lt;Middle /&gt;  //子组件
&lt;/BatteryContext.Provider&gt;</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 18px"><span style="font-size: 16px">&nbsp;为了方便看出效果,将定义一个子组件和一个孙组件。然后不通过子组件,孙组件直接取值</span>。</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">import React, { Component, createContext } from 'react'<span style="color: rgba(0, 0, 0, 1)">;

const BatteryContext </span>=<span style="color: rgba(0, 0, 0, 1)"> createContext();

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">声明一个孙组件</span>
<span style="color: rgba(0, 0, 0, 1)">class Leaf extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
   
    )
}
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">声明一个子组件</span>
<span style="color: rgba(0, 0, 0, 1)">class Middle extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> &lt;Leaf /&gt;
<span style="color: rgba(0, 0, 0, 1)">}
}

class App extends Component {
render(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Provider value={60}&gt;
      &lt;Middle /&gt;
      &lt;/BatteryContext.Provider&gt;
<span style="color: rgba(0, 0, 0, 1)">    );
}
}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> App;</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px">孙组件需要BatteryContext.Consumer来接收值,Consumer里面不能直接渲染其他组件,而是要声明一个函数。函数的参数就是context的值。</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 0, 1)">class Leaf extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Consumer&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
          battery </span>=&gt; &lt;h1&gt;Battery : {battery}&lt;/h1&gt;
<span style="color: rgba(0, 0, 0, 1)">      }
      </span>&lt;/BatteryContext.Consumer&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}</span></span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px">&nbsp;效果图;</span></p>
<p><img src="https://img2018.cnblogs.com/blog/1557620/201907/1557620-20190721155550531-814465393.jpg" alt=""></p>
<p>&nbsp;</p>
<p><span style="font-size: 16px">这样没通过Middle组件来传递值,但是Leaf组件能通过context来获得属性。这就是context的基本用法。</span></p>
<p>&nbsp;</p>
<div><strong><span style="font-size: 14pt">context不但能跨层级来传递属性值,还能在属性值发生变化的时候重渲染Consumer下面的元素,举个例子:</span></strong></div>
<div>&nbsp;</div>
<div><span style="font-size: 16px">在state中定义battery并赋值</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">state =<span style="color: rgba(0, 0, 0, 1)"> {
    battery: </span>60<span style="color: rgba(0, 0, 0, 1)">
}</span></span></pre>
</div>
<p>&nbsp;</p>
</div>
<div><span style="font-size: 16px">然后做一个按钮,每次点击的时候都要battery减一。&nbsp; 代码:</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 0, 1)">render() {
    const { battery } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state;
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Provider value={battery}&gt;
      &lt;<span style="color: rgba(0, 0, 0, 1)">button
          type</span>="button"<span style="color: rgba(0, 0, 0, 1)">
          onClick</span>={() =&gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.setState({ battery: battery - 1<span style="color: rgba(0, 0, 0, 1)"> })}
      </span>&gt;<span style="color: rgba(0, 0, 0, 1)">
          减减
      </span>&lt;/button&gt;
      &lt;Middle /&gt;
      &lt;/BatteryContext.Provider&gt;
<span style="color: rgba(0, 0, 0, 1)">    );
}</span></span></pre>
</div>
<p>&nbsp;</p>
</div>
<div><span style="font-size: 16px">全部代码:</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">import React, { Component, createContext } from 'react'<span style="color: rgba(0, 0, 0, 1)">;

const BatteryContext </span>=<span style="color: rgba(0, 0, 0, 1)"> createContext();

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">声明一个孙组件</span>
<span style="color: rgba(0, 0, 0, 1)">class Leaf extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Consumer&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
          battery </span>=&gt; &lt;h1&gt;Battery : {battery}&lt;/h1&gt;
<span style="color: rgba(0, 0, 0, 1)">      }
      </span>&lt;/BatteryContext.Consumer&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">声明一个子组件</span>
<span style="color: rgba(0, 0, 0, 1)">class Middle extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> &lt;Leaf /&gt;
<span style="color: rgba(0, 0, 0, 1)">}
}

class App extends Component {
state </span>=<span style="color: rgba(0, 0, 0, 1)"> {
    battery: </span>60<span style="color: rgba(0, 0, 0, 1)">
}
render() {
    const { battery } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state;
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Provider value={battery}&gt;
      &lt;<span style="color: rgba(0, 0, 0, 1)">button
          type</span>="button"<span style="color: rgba(0, 0, 0, 1)">
          onClick</span>={() =&gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.setState({ battery: battery - 1<span style="color: rgba(0, 0, 0, 1)"> })}
      </span>&gt;<span style="color: rgba(0, 0, 0, 1)">
          减减
      </span>&lt;/button&gt;
      &lt;Middle /&gt;
      &lt;/BatteryContext.Provider&gt;
<span style="color: rgba(0, 0, 0, 1)">    );
}

}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> App;</span></pre>
</div>
<p>&nbsp;</p>
</div>
<p><span style="font-size: 16px">&nbsp;效果图:&nbsp;</span></p>
<p><img src="https://img2018.cnblogs.com/blog/1557620/201907/1557620-20190721160107492-769117216.jpg" alt=""></p>
<p>&nbsp;</p>
<p><span style="font-size: 18px">这样每次点击都会使battery得数值发生变化,从而重渲染Consumer下面的元素。</span></p>
<p>&nbsp;</p>
<div><strong><span style="font-size: 14pt">如果有多个Context该怎么做呢?我们在创建一个 Context</span></strong></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">const OnLineContext = createContext();</span></pre>
</div>
<p>&nbsp;</p>
<div><span style="font-size: 16px">如果有多个context变量的话,只需要把Privider嵌套进来即可,顺序不重要。接下来声明online的Provider了。</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 0, 1)">class App extends Component {
state </span>=<span style="color: rgba(0, 0, 0, 1)"> {
    battery: </span>60<span style="color: rgba(0, 0, 0, 1)">,
    online: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
render() {
    const { battery, online } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state;
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Provider value={battery}&gt;
      &lt;OnLineContext.Provider value={online} &gt;
          &lt;<span style="color: rgba(0, 0, 0, 1)">button
            type</span>="button"<span style="color: rgba(0, 0, 0, 1)">
            onClick</span>={() =&gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.setState({ battery: battery - 1<span style="color: rgba(0, 0, 0, 1)"> })}
          </span>&gt;<span style="color: rgba(0, 0, 0, 1)">
            减减
      </span>&lt;/button&gt;
          &lt;<span style="color: rgba(0, 0, 0, 1)">button
            type</span>="button"<span style="color: rgba(0, 0, 0, 1)">
            onClick</span>={() =&gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.setState({ online: !<span style="color: rgba(0, 0, 0, 1)">online })}
          </span>&gt;<span style="color: rgba(0, 0, 0, 1)">
            Switch
      </span>&lt;/button&gt;
          &lt;Middle /&gt;
      &lt;/OnLineContext.Provider&gt;
      &lt;/BatteryContext.Provider&gt;
<span style="color: rgba(0, 0, 0, 1)">    );
}</span></span></pre>
</div>
<p>&nbsp;</p>
</div>
</div>
<div><span style="font-size: 16px">与Provider类似。Consumer也需要嵌套,顺序不重要。只要Consumer需要声明函数,所以要注意语法。</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 0, 0, 1)">class Leaf extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Consumer&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
          battery </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> (
            </span>&lt;OnLineContext.Consumer&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                online </span>=&gt; &lt;h1&gt;Battery : {battery} , Online : {online.toString()}&lt;/h1&gt;
<span style="color: rgba(0, 0, 0, 1)">            }
            </span>&lt;/OnLineContext.Consumer&gt;
<span style="color: rgba(0, 0, 0, 1)">          )
      }
      </span>&lt;/BatteryContext.Consumer&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}</span></span></pre>
</div>
<p><span style="font-size: 16px">&nbsp;</span></p>
</div>
<p><span style="font-size: 16px">&nbsp;全部代码:</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">import React, { Component, createContext } from 'react'<span style="color: rgba(0, 0, 0, 1)">;

const BatteryContext </span>=<span style="color: rgba(0, 0, 0, 1)"> createContext();
const OnLineContext </span>=<span style="color: rgba(0, 0, 0, 1)"> createContext();

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">声明一个孙组件</span>
<span style="color: rgba(0, 0, 0, 1)">class Leaf extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">与Provider类似。Consumer也需要嵌套,顺序不重要。只要Consumer需要声明函数,所以要注意语法。</span>
      &lt;BatteryContext.Consumer&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
          battery </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> (
            </span>&lt;OnLineContext.Consumer&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                online </span>=&gt; &lt;h1&gt;Battery : {battery} , Online : {online.toString()}&lt;/h1&gt;
<span style="color: rgba(0, 0, 0, 1)">            }
            </span>&lt;/OnLineContext.Consumer&gt;
<span style="color: rgba(0, 0, 0, 1)">          )
      }
      </span>&lt;/BatteryContext.Consumer&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">声明一个子组件</span>
<span style="color: rgba(0, 0, 0, 1)">class Middle extends Component {
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> &lt;Leaf /&gt;
<span style="color: rgba(0, 0, 0, 1)">}
}

class App extends Component {
state </span>=<span style="color: rgba(0, 0, 0, 1)"> {
    battery: </span>60<span style="color: rgba(0, 0, 0, 1)">,
    online: </span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">
}
render() {
    const { battery, online } </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.state;
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">接下来声明online的Provider了。如果有多个context变量的话,只需要把Privider嵌套进来即可,顺序不重要。</span>
    <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;BatteryContext.Provider value={battery}&gt;
      &lt;OnLineContext.Provider value={online} &gt;
          &lt;<span style="color: rgba(0, 0, 0, 1)">button
            type</span>="button"<span style="color: rgba(0, 0, 0, 1)">
            onClick</span>={() =&gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.setState({ battery: battery - 1<span style="color: rgba(0, 0, 0, 1)"> })}
          </span>&gt;<span style="color: rgba(0, 0, 0, 1)">
            减减
      </span>&lt;/button&gt;
          &lt;<span style="color: rgba(0, 0, 0, 1)">button
            type</span>="button"<span style="color: rgba(0, 0, 0, 1)">
            onClick</span>={() =&gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.setState({ online: !<span style="color: rgba(0, 0, 0, 1)">online })}
          </span>&gt;<span style="color: rgba(0, 0, 0, 1)">
            Switch
      </span>&lt;/button&gt;
          &lt;Middle /&gt;
      &lt;/OnLineContext.Provider&gt;
      &lt;/BatteryContext.Provider&gt;
<span style="color: rgba(0, 0, 0, 1)">    );
}

}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> App;</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px">效果图:</span></p>
<p><img src="https://img2018.cnblogs.com/blog/1557620/201907/1557620-20190721160703650-408113861.jpg" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div><strong><span style="font-size: 18px">还有一个问题 , 如果Consumer向上找不到对应的Provider怎么办?</span></strong></div>
<div>&nbsp;</div>
<div>
<div><strong><span style="font-size: 18px">其实即使找不到也不会报错,而是显示为空。那怎么设置默认值呢?</span></strong></div>
<div>&nbsp;</div>
</div>
<div><span style="font-size: 16px">那上面的demo举例 ,刚才我们设置的battery为60。如果Consumer向上找不到BatteryContext.Provider的值,我们可以这样设置默认值:</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">const BatteryContext = createContext(30);</span></pre>
</div>
<div><span style="font-size: 16px">这样BatteryContext.Consumer向上找不到值,就会取默认值30。</span></div>
</div>
<p>&nbsp;</p>
<div>
<div><strong><span style="font-size: 18px">context不仅仅只是可以传数值,也可以传函数。大家可以试试看。</span></strong></div>
<div><strong><span style="font-size: 18px">最后再提示一下大家,不要滥用context,不然会影响组件的独立性。 如果一个组件中只使用一个Context的话,就可以使用contextType代替Consumer。详见https://www.cnblogs.com/littleSpill/p/11221817.html</span></strong></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/littleSpill/p/11221538.html
頁: [1]
查看完整版本: React的Context的使用方法简介