成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[ 一起學(xué)React系列 -- 4 ] 透傳的Context

firim / 2280人閱讀

摘要:官方對的介紹是意思就是提供了一種通過組件樹傳遞數(shù)據(jù)的方法,而無需在每個級別手動傳遞。這也是基于重要物證哈哈實例使用學(xué)習(xí)技術(shù)最終是要有產(chǎn)出的。依然被視作一個組件,不過不同的是它的子組件必須是一個方法并且該方法接收當前對象并最終返回一個節(jié)點。

拋轉(zhuǎn)引玉

通過上一篇的科普我們知道如果父節(jié)點需要向子節(jié)點傳遞數(shù)據(jù),那么就得通過Props來實現(xiàn);那么擺在我們眼前的就有一個問題了:現(xiàn)有N個節(jié)點并且它們都是嵌套成父子結(jié)構(gòu),大致如下


    
        
            
                ......
                
            
        
    

如過last組件需要A組件的某個數(shù)據(jù),按照之前的說法我們可以使用Props;但是我覺得一般人都不會這么做,為什么?一個數(shù)據(jù)在N個組件中通過Props傳遞,首先寫法上會很榮譽、其次就是很可能在某個節(jié)點寫錯了造成最終拿到的數(shù)據(jù)不是想要的數(shù)據(jù),這些都是我們需要考慮的問題。當然有人會想到使用Redux或者Mobx這種第三方庫來解決,沒毛??;但如果只是一個小小的需求就引入了一個庫,是不是殺雞用了牛刀?在這個問題上React本身有自己的解決方案:Context。

Context是什么?

目前React的Context API已經(jīng)出了兩版,在React16.3.0版本之前和之后。實際上我們開發(fā)React項目時候很少會用到這個API(至少小編身邊是這種情況);而且對于第一版的Context就連官方也不建議用,首先是不好用其次是問題多,不過即使如此不堪的技術(shù)卻是Redux的基礎(chǔ)技術(shù),真的是厲害了!
后來在React16.3.0版本更新之后,全新的Context API與我們見面,可以說是脫胎換骨。官方對Context的介紹是:

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

意思就是Context提供了一種通過組件樹傳遞數(shù)據(jù)的方法,而無需在每個級別手動傳遞props。可以看出這個技術(shù)剛好可以用來解決我們前面提出的問題。

Context可以做什么?

事實上官方設(shè)計這個API的目的是共享可被視為React組件樹的“全局”數(shù)據(jù),例如當前經(jīng)過身份驗證的用戶,主題或首選語言。意圖言簡意賅,可以理解成為React組件樹(從Root節(jié)點開始通過不斷組合各個組件形成最終的樹形結(jié)構(gòu))中注入了一個上下文對象同時將一些全局通用的數(shù)據(jù)放在這個對象中,這樣我們就可以在這個組件樹的任何地方使用這些數(shù)據(jù)。

如何使用Context?

針對新版Context,官方給我們提供了三個API:

React.createContext

Provider

Consumer

通過字面意思大家應(yīng)該就能猜到它們分別的作用了吧!

React.createContext: 用來創(chuàng)建Context對象
Provider: 用來向組件樹發(fā)出Context對象
Consumer: 使用Context對象

不過呢,后兩者其實是React.createContext創(chuàng)建出來的對象的組成,用一段代碼來解釋吧:

const {Provider, Consumer} = React.createContext(defaultValue);

嗯...就醬紫?。。?!
其實寫到這里我相信用過Redux的朋友就已經(jīng)開始覺得眼熟了,就是ProvidercreateContext。因為react-redux提供Provider, Redux提供createStore。這也是Redux基于Context API重要物證哈哈....

實例使用Context

學(xué)習(xí)技術(shù)最終是要有產(chǎn)出的。筆者也一步一步來實現(xiàn)一個簡單例子,功能:通過點擊按鈕對屏幕中數(shù)字進行加1操作
首先我們需要創(chuàng)建兩個js文件:

buildContext.js
import {createContext} from "react";

const defaultData = {};
export const {Provider, Consumer} = createContext(defaultData);

這里可能有人會有疑問:為什么將創(chuàng)建Context多帶帶抽離出來?
1) 將Context和組件隔離;因為它們不存在必要的聯(lián)系,Context只是單純的注入組件而已。
2) 因為Provider, Consumer需要配對使用(注意:Provider, Consumer配對使用的前提是它們都來自同一個createContext);我們可以在Provider下的任意節(jié)點使用Consumer,所以就可能存在Provider, Consumer不在同一個組件的情況,所以將將創(chuàng)建Context多帶帶抽離出來使得處理Context更加優(yōu)雅。

ContextDemo.js
import React, {Component} from "react"
import {Provider, Consumer} from "./buildContext";

class ContextDemo extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: 0
        };
    }

    addOne = () => {
        this.setState((preState) => ({
                    count: preState.count + 1
                }
            )
        )
    };

    render() {
        return (
            
{ (context) =>

{context.count}

}
) } } export default ContextDemo

這里我們重點解釋下Provider與Consumer:

Provider
被視作一個React組件,它的作用就是接收一個value屬性并把它當做最終Context實體注入到Provider的所有子組件中;同時Provider允許被Consumer訂閱一個或多個Context的變動,也就是說Provider內(nèi)部可以有N個Consumer并且它們都可以拿到最新&&相同的Context對象。

如例子所示,我們將組件的State對象注入到Provider字組件中,如果State發(fā)生變化那么Provider中的Context對象必定會同步發(fā)生變化。

Consumer
依然被視作一個React組件,不過不同的是它的子組件必須是一個方法并且該方法接收當前Context對象并最終返回一個React節(jié)點。同時這里有兩個問題需要重點關(guān)注:

Consumer接收到的Context對象為離它最近的那個Provider注入的Context對象(且必須是通過value屬性)。因為Provider作為一個組件也可以進行嵌套。不過筆者認為多帶帶一個React項目最好只存在一個Context對象而且應(yīng)該作為一個App級的Context對象(也就是將項目的根節(jié)點作為Provider的子組件)。這樣做筆者認為有兩個好處:1)全局只有一個Context更有利于方便使用和管理;2)作為一個App級的Context對象可以讓我們在項目的任何一個地方使用到Context對象,發(fā)揮Context最大的力量。

如果Provider不存在(如果存在那么必須要有value屬性,否則報錯),那么Consumer獲取到的Context對象為最初createContext方法的默認參數(shù)。

綜上所述:Provider的value == Consumer子組件(function)的入?yún)?/b>

當我們理解了這兩個概念,我們再回過頭來看代碼;
我們將組件的State(this.state)通過Provider注入到其子組件中,其實可以預(yù)料到當我們更改State時候Context對象也會同步變化最終保持一致。所以:


    {
        (context) => 

{context.count}

}

此時Consumer的子組件(function)的入?yún)?b>context就可以認為是this.state的復(fù)制體,所以可以在方法中獲取到相應(yīng)的數(shù)據(jù)并且在點擊按鈕更改了State后Context也發(fā)生變化,從而實現(xiàn)UI的重新渲染。

小小的測試

前面有句話說:Provider, Consumer配對使用的前提是它們都來自同一個createContext。因此筆者針對這點做了兩個實驗,目的是測試當Provider, Consumer不是來自同一個createContext會出現(xiàn)什么情況。這里新建兩個文件buildContext.js和ContextTest.js

情況一
buildContext.js
import {createContext} from "react";

export const {Provider} = createContext({"name": "Mario"});
export const {Consumer} = createContext({"age": "26"});
ContextTest.js
import React, {Component} from "react";
import {Provider, Consumer} from "./buildContext";

class Context extends Component {
    render() {
        return (
            {/*name*/}
                {/*age*/}
                    {
                        (context) => (
                            

age: {context.age}

name: {context.name}

) }
) } } export default Context;

運行的結(jié)果有點意想不到,Consumer拿到的Context并不是離它最近的Provider提供的,而是創(chuàng)造它的createContext方法的默認值,即:export const {Consumer} = createContext({"age": "26"});。再換個寫法看看!

情況二
buildContext.js
import {createContext} from "react";

export const NameContext = createContext({"name": "Mario"});
export const AgeContext = createContext({"age": "26"});
ContextTest.js
import React, {Component} from "react";
import {NameContext, AgeContext} from "./buildContext";

class Context extends Component {
    render() {
        return (
            {/*name*/}
                {/*age*/}
                    {
                        (context) => (
                            

age: {context.age}

name: {context.name}

) }
) } } export default Context;;

這里我們給Provider提供一個value屬性;

運行結(jié)果與第一種情況相同;

結(jié)論

因此我們可以猜測:如果Provider, Consumer不是來自同一個createContext,那么Consumer獲取到的Context則是自己的createContext方法的默認值,此時的Provider被視為不存在。

Context的簡單實用就介紹到這里,本篇很多地方都來自筆者的個人看法,如有理解不當煩請丟磚。
同時筆者也嘗試寫了一個更具有代表性(純屬筆者意淫)的Context應(yīng)用實例,將Context、ContextHandler、Component分離出來,實現(xiàn)更改相鄰組件的樣式。麻雀雖小五臟俱全,請各位朋友多多海涵!!
對了項目啟動腳本是npm install || npm start

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/97894.html

相關(guān)文章

  • 十個案例學(xué)React Hooks

    摘要:在線傳遞給的是而不是,返回值即是想要透傳的數(shù)據(jù)了。所以函數(shù)組件在每次渲染的時候如果有傳遞函數(shù)的話都會重渲染子組件。在學(xué)會使用React Hooks之前,可以先看一下相關(guān)原理學(xué)習(xí)React Hooks 前言 在 React 的世界中,有容器組件和 UI 組件之分,在 React Hooks 出現(xiàn)之前,UI 組件我們可以使用函數(shù),無狀態(tài)組件來展示 UI,而對于容器組件,函數(shù)組件就顯得無能為力,我...

    williamwen1986 評論0 收藏0
  • [ 一起學(xué)React系列 -- 12 ] React-Router4 (2)

    摘要:驗證路由所謂的驗證路由其實就是該路由的外層加了一層驗證機制,有授權(quán)的用戶才能進入,反之都無法進入。一起學(xué)系列也隨著這篇的結(jié)束而告一段落了。大家一起加油最后再獻上和本篇博文有關(guān)的代碼鏈接和示例頁面 時隔那么久,博主終于從睡夢中醒來開始更新博客啦!為自己的勤勞歡呼...(pia pia pia打臉)!本次我們接著上一篇博客繼續(xù)聊React-Router4。上篇我們主要了解了React-Ro...

    chaos_G 評論0 收藏0
  • 30分鐘精通React今年最勁爆的新特性——React Hooks

    摘要:所以我們做的事情其實就是,聲明了一個狀態(tài)變量,把它的初始值設(shè)為,同時提供了一個可以更改的函數(shù)。 你還在為該使用無狀態(tài)組件(Function)還是有狀態(tài)組件(Class)而煩惱嗎? ——擁有了hooks,你再也不需要寫Class了,你的所有組件都將是Function。 你還在為搞不清使用哪個生命周期鉤子函數(shù)而日夜難眠嗎? ——擁有了Hooks,生命周期鉤子函數(shù)可以先丟一邊了。 你在還...

    icattlecoder 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<