react 入門與進階教程


react 入門與進階教程

 

前端學習對於我們來說越來越不友好,特別是隨着這幾年的發展,入門門檻越來越高,連進階道路都變成了一場馬拉松。在學習過程中,我們面臨很多選擇,vue與react便是一個兩難的選擇。

兩者都是非常優秀的框架,而且我不能非常主觀的說誰好誰不好。但是從我們初學者的角度來說,其實我們沒有必要去考慮誰的性能更好,誰的實現更優雅,誰更適合什么場景等各種因素,唯一一個需要考慮的標准就是,學習誰,能夠讓我們更快的掌握它。因為無論他們兩個你掌握了誰,都能夠讓你在找工作時更有底氣。這就足夠了。

因此,我這篇文章的目的,則是希望從與官方文檔不同的角度,來試圖讓react學習變得更加容易,如果你想要學習react,不妨花點時間讀下去。

為什么對於新人來說,官方文檔不能幫助你掌握得更好

對於vue的學習,很多朋友有一個大的誤解,認為vue官方出了中文文檔,所以掌握起來會更加容易。然而事實上並非如此。

官方文檔可能告訴了你vue/react的基礎知識有哪些,可是這些知識怎么用,官方文檔並沒有告訴我們。而且vue官方文檔為了降低學習門檻(繞開了vue-cli),在講述知識的時候,不少地方其實與實際開發是有差距的,這個差距會導致你看完了官方文檔,仍然不知道如何使用vue做一些事情。

當然,這樣的問題,react官方文檔也存在。雖然對於經驗豐富的大神來說,這並不是問題,但是對於新人來說,這樣的差距往往會使得大家有一種似懂非懂的感覺。

這也是我為什么要從和官方文檔不一樣的角度來入手的原因。

react中文文檔:http://www.react-cn.com/docs/getting-started.html

學前准備

在准備學習本文的react知識之前,希望你已經擁有了ES6的知識與知道了create-react-app的安裝與使用,我們的學習將會建立在這基礎之上,如果你暫時還沒有接觸過他們,不用擔心,可以回過頭去閱讀我的前兩篇文章。不用花太多時間就可以初步掌握。

ES6常用知識合集
詳解create-react-app 與 ES6 modules

你可以暫時不用對react有什么基礎的了解,我們可以從0開始,當然,如果你看過官方文檔或者從其他地方學習過相關知識就更好了。

react官方中文文檔

開始啦,萬能的Hello World程序

首先,假設你已經在電腦上安裝好了create-react-app並知道如何使用,那么我就開始在你電腦上存放開發項目的目錄(本文中假設為develop)里開始創建一個名為first-react的react項目。操作順序如下:

啟動之后,效果分別如下圖所示:

命令行工具中

瀏覽器中

自動生成的項目是一個簡單的react demo。這個時候項目中會有三個文件夾,我們來分別了解一下這三個文件夾的作用。

  • node_modules
    項目依賴包存放位置。當我們運行npm install安裝package.json中的依賴包時,該文件夾會自動創建,所有的依賴包會安裝到該文件夾里。
  • public
    主要的作用是html入口文件的存放。當然我們也可以存放其他公用的靜態資源,如圖片,css等。其中的index.html就是我們項目的入口html文件。
  • src
    組件的存放目錄。在create-react-app創建的項目中,每一個單獨的文件都可以被看成一個單獨的模塊,單獨的image,單獨的css,單獨js等,而所有的組件都存放於src目錄中,其中index.js則是js的入口文件。雖然我們並沒有在index.html中使用script標簽引入他,但是他的作用就和此一樣。

我們在最初學習開發一個頁面的時候,就已經知道一個頁面會有一個html文件,比如index.html,然后分別在html文件中,通過script與link標簽引入js與css。但是在構建工具中,我們只需要按照一定的規則來組織文件即可,整合的工作構建工具會自動幫助我們完成,這也是構建工具給前端開發帶來的便利之處,也因為如此,前端的模塊化開發才成為了可能。

我們還是和上一篇文章中說的一樣,先清空src目錄里所有的其他文件,僅僅只留下空的入口文件index.js,並在index.js寫入如下的代碼:

 

 

保存之后,結果如下:

Hello World!

如何你能輕松看懂這四行代碼,那么說明你離掌握react已經不遠了。至少你已經掌握了ES6的相關知識。我來解釋一下這些代碼的作用。

  • import React from 'react';
    在我們通過npm install指令安裝依賴包的時候,就已經安裝好了react,因此我們可以直接import。這句話的作用就在於,能夠讓構建工具在當前模塊中識別jsx。而jsx,是一種類似於html標簽的模板語言,我們只需要懂得html標簽,就不必花費額外的精力去了解jsx,因為我們可以直接理解為它就是html標簽,但是在此基礎上,擴展了更多的能力。例如這里,程序能夠識別

     

    Hello World!

    ,正是這句話的作用。

  • import { render } from 'react-dom';
    這是利用ES6的解析結構的語法,僅僅引入了react-domrender方法。render方法的作用,就是將react組件,渲染進DOM結構中,它的第一個參數就是react 組件,第二個參數則是一個DOM元素對象。
  • const root = document.querySelector('#root');
    這句話就很簡答了,如果你理解不了,那么說明你的基礎還不足以支撐你學習react, – -。
  • render(<div>Hello World!</div>, root);
    這是最核心的一步,通過 render方法,將寫好的react組件渲染進DOM元素對象。而這里的 root,則是在 index.html中寫好的一個元素。這里的 div,可以理解為一個最簡單的react組件。

OK,理解了這些,那么我們就可以開始學習react最核心的內容組件了。

react組件

曾經,創建react組件有三種方式,但是既然都決定在ES6的基礎上來學習react了,那么我也就只介紹其中的兩種方式了。反正另外一種方式也已經被官方廢棄。

當一個組件,並沒有額外的邏輯處理,僅僅只是用於數據的展示時,我們推薦使用函數式的方式來創建一個無狀態組件。

我們結合簡單的例子來理解。在項目的src目錄里創建一個叫做helloWorld.jsx的文件。在該文件中,我們將創建一個正式的react組件,代碼如下:

 

 

並在index.js中引入該組件。修改index.js代碼如下:

保存后運行,我們發現結果一樣。

helloWorld.jsx中,我們仍然引入了react,是因為所有會涉及到jsx模板的組件,我們都要引入它,這樣構建工具才會識別得到。

組件里只是簡單的創建了一個HelloWorld函數,並返回了一段html(jsx模板)。並在最后將HelloWorld函數作為對外的接口暴露出來export default HelloWorld

接下來我們通過一點一點擴展HelloWorld組件能力的方式,來學習組件相關的基礎知識。

向組件內部傳遞參數

向組件內部傳遞參數的方式很簡單,這就和在html標簽上添加一個屬性一樣。

例如我們希望向HelloWorld組件內傳遞一個name屬性。那么只需要我們在使用該組件的時候,添加一個屬性即可。

如果我們希望組件最終渲染的結果是諸如:Tom say: Hello, world!其中的名字可以在傳入時自定義。那么我們在組件中應該如何接收傳遞進來的參數呢?

我們修改HelloWorld.jsx如下:

 

 

並在index.js中修改render方法的使用,向組件中傳入一個name屬性

結果如下:

輸出props參數

HelloWorld組件中,我使用了一個叫做props的參數。而通過打印出來props可以得知,props正是一個組件在使用時,所有傳遞進來屬性組合而成的一個對象。大家也可以在學習時多傳入幾個額外的參數,他們都會出現在props對象里。

而在jsx模板中,通過

{ props.name } say: Hello World!

這樣的方式來將變量傳入進來。這是jsx模板語言支持的一種語法,大家記住能用即可。

大家要記住,使用這種方式創建的無狀態組件,會比另外一種方式性能更高,因此如果你的組件僅僅只是用於簡單的數據展示,沒有額外的邏輯處理,就要優先選擇這種方式。

那么我們繼續升級HelloWorld組件的能力。現在我希望有一個點擊事件,當我們點擊該組件時,會在Console工具中打印出傳入的name值。這就涉及到了另外一種組件的創建,也就是當我們的組件開始有邏輯處理,之前的那種方式勝任不了時索要采取的一種形式。

修改helloWorld.jsx文件如下:

 

 

如果,你同時熟知第一種react組件的創建方式,與ES6語法的話,相信上面的代碼,並不會對你造成多少困擾。

沒錯,這種方式創建的組件,正是通過繼承react的Component對象而來。所以創建的方式也是利用ES6的class語法來生成。也正因為如此,其中的很多實用方式,也就跟class的使用一樣了。

上面的render方法,則是Component中,專門提供的用來處理jsx模板的方法。

與第一種方式不同的是,我們接收傳入進來的參數,使用的是this.props,第一種方式將props放置於函數參數中,而這種方式則是將props掛載與實例對象上,因此會有所不同。

而我們想要給一個組件添加點擊事件,方式也與html標簽中幾乎一致

 

react事件相關的知識大家可以當做一個進階課程去研究,這里就暫時不多說,詳情可以參考官方文檔 https://facebook.github.io/react/docs/events.html

好了,現在大家初步認識了react的第二種組件的創建方式,那么我們繼續搞事情,現在我想要的效果,是傳入兩個名字,name1=Tom, name2='Jason',我希望第一次點擊時,log出Tom,第二次log出Jason,第三次Tom…

這個時候,我們就需要引入react組件非常核心的知識狀態state

修改helloWorld.jsx代碼如下:

 

 

 

先來說說state相關的基礎知識。首先了解ES6 class語法的同學都應該知道,當我們通過這種方式來寫的時候,其實是將state寫入了構造函數之中。

 

因此深入掌握class語法對於學習react組件的幫助非常巨大,我們需要清楚的知道什么樣的寫法會放入對象的什么位置,是構造函數中,還是原型中等。這也是為什么開篇我會強調一定要先對我的前兩篇文章所介紹的知識有一定了解才行。

因此,在對象中,我們可以通過this.state的方式來訪問state中所存儲的屬性。同時,react還提供了如下的方式來修改state的值

setState接收一個對象,它的運行結果類似於執行一次assign方法。會修改傳入的屬性,而其他的屬性則保持不變。

react賦予state的特性,則是當state被修改時,會引起組件的一次重新渲染。即render方法會重新執行一次。也正是由於這個特性,因此當我們想要改變界面上的元素內容時,常常只需要改變state中的值就行了。這也是為什么結合render方法,我們可以不再需要jquery的原因所在。

setState也有一個非常重要的特性,那就是,該方法是異步的。它並不會立即執行,而會在下一輪事件循環中執行。

說到這里,基礎薄弱的同學就開始頭暈了,這就是為什么我在前面的文章都反復強調基礎知識的重要性,基礎扎實,很多東西稍微一提,你就知道是怎么回事,不扎實,到處都是讓你頭暈的點,不知道的沒關系,讀我這篇文章 http://www.jianshu.com/p/12b9f73c5a4f。

相信不理解這個點的同學肯定會遇到很多坑,所以千萬要記住了。

 

refs

我們知道,react組件其實是虛擬DOM,因此通常我們需要通過特殊的方式才能拿到真正的DOM元素。大概說一說虛擬DOM是個什么形式存在的,它其實就是通過js對象的方式將DOM元素相關的都存儲其實,比如一個div元素可能會是這樣:

而我們想要拿到真實的DOM元素,react中提供了一種叫做ref的屬性來實現這個目的。

修改helloWorld.jsx如下:

 

 

為了區分ES6語法中的class關鍵字,當我們在jsx中給元素添加class時,需要使用className來代替

我們在jsx中,可以給元素添加ref屬性,而這些擁有ref屬性的元素,會統一放在組件對象的refs中,因此,當我們想要訪問對應的真實DOM時,則通過this.refs來訪問即可。

refs

當然,ref的值不僅僅可以為一個名字,同時還可以為一個回調函數,這個函數會在render渲染時執行,也就是說,每當render函數執行一次,ref的回調函數也會執行一次。

修改helloWorld.jsx如下,感受一下ref回調的知識點

 

 

大概介紹一下我暫時能想到的ref使用的一個場景。例如我們要實現元素拖拽的時候,或者寫一個slider組件。我們可能會非常頻繁的改動元素的位置。這個時候,如果我們仍然通過react組件的state來存儲元素的位置,那么就會導致react組件過於頻繁的渲染,這就會引發一個嚴重的性能問題。所以這個時候我們不得不獲取到真實DOM,並通過常規的方式來做。

同樣的道理也適用於vue中,我們要盡量避免將可能會變動頻率非常高的屬性存放於vue組件的data中。

組件生命周期

所謂組件的生命周期,指的就是一個組件,從創建到銷毀的這樣一個過程。

而react為組件的生命周期提供了很多的鈎子函數。很多地方也為生命周期畫了很清晰明了的圖幫助大家理解。但是我在初學的時候其實並沒有看懂,還是在我懂得了生命周期之后,才看懂的那些圖。所以呢,這里我也就不去找圖了。我們這樣理解。

通俗來說,react為一個組件,划分了如下的時刻。

  • 組件第一次渲染完成的前后時刻,
    componentWillMount 渲染完成之前
    componentDidMount 渲染完成之后

所謂的渲染完成,即組件已經被渲染成為真實DOM並插入到了html之中。

  • 組件屬性(我們前面提到的props與state)更新的前后時刻
    componentWillReceiveProps接收到一個新的props時,在重新render之前調用
    shouldComponentUpdate 接收到一個新的state或者props時,在重新render之前調用
    componentWillUpdate 接收到一個新的state或者props時,在重新render之前調用
    componentDidUpdate 組件完成更新之后調用
  • 組件取消掛載之前(取消之后就沒必要提供鈎子函數了)
    componentWillUnmount

在學習之初你不用記住這些函數的具體名字,你只需要記住這三個大的時刻即可,第一次渲染完成前后,更新前后,取消之前。當你要使用時,再查具體對應的名字叫什么即可。

而且根據我的經驗,初學之時,其實也不知道這些鈎子函數會有什么用,會在什么時候用,這需要我們在實踐中慢慢掌握,所以也不用着急。當我們上手寫了幾個稍微復雜的例子,自然會知道如何去使用他們。

所以這里我只詳細介紹一下,我們最常用的一個生命周期構造函數,組件第一次渲染完成之后調用的componentDidMount

既然是組件第一次渲染完成之后才會調用,也就是說,該函數在react組件的生命周期中,只會調用一次。而渲染完成,則表示組件已經被渲染成為真實DOM插入了html中。所以這時候就可以通過ref獲取真實元素。記住它的特點,這會幫助我們正確的使用它。

修改helloWorld.jsx如下:

我們在實際開發中,常常需要通過ajax獲取數據,而數據請求的這個行為,則最適合放在componentDidMount中來執行。

通常會在首次渲染改變組件狀態(state)的行為,或者稱之為有副作用的行為,都建議放在componentDidMount中來執行。主要是因為state的改動會引發組件的重新渲染。

組件之間的交互

作為react學習中的一個非常重要的點,組件之間的交互還是需要我們認真掌握的。這個時候hello world就滿足不了我們學習的欲望了,所以我們可以先把它給刪掉。

那么組件之間的交互,大概可以分為如下兩種:

  • 父組件與子組件之間交互
  • 子組件與子組件之間交互

當然可能有的人會問,2個不相干的組件之間如何交互?如果,你的代碼里,出現了兩個不相干的組件還要交互,那說明你的組件划分肯定是有問題的。這就是典型的給自己挖坑找事兒。即使確實有,那也是通過react-redux把他們變成子組件對吧。但是,通常情況下,不到萬不得已,並不建議使用react-redux,除非你的項目確實非常龐大了,需要管理的狀態非常多了,已經不得不使用,一定要記住,react-redux這類狀態管理器是最后的選擇。

我們來想想一個簡單常見的場景:頁面里有一個submit提交按鈕,當我們點擊提交后,按鈕前出現一個loading圖,並變為不可點擊狀態,片刻之后,接口請求成功,飄出一個彈窗,告訴你,提交成功。大家可以想一想,這種場景,借助react組件應該如何做?

首先可以很簡單的想到,將按鈕與彈窗分別划分為兩個不同的組件:

。然后創建一個父組件來管理這兩個子組件

那么在父組件中,我們需要考慮什么因素?Button的loading圖是否展示,彈窗是否展示對吧。

OK,根據這些思考,我們開始來實現這個簡單的場景。

首先創建一個Button組件。在src目錄下創建一個叫做Button.jsx的文件,代碼如下:

 

注意,當你引入了一個新創建的文件時,可能需要重新啟動服務才會找得到新的組件

由於這里的Button組件僅僅是簡單的展示,並無額外的邏輯需要處理,因此我們使用無狀態的組件。在這個組件里,出現了一個新的知識點:children

當然,children還可以是更多的元素,這和我們熟知的DOM元素的children保持一致。

還有一個需要注意的知識點,則是在jsx模板中,我們可以使用JavaScript表達式來執行簡單的邏輯處理

我們可以列舉一些常見的表達式:

 

如果對於JavaScript表達式了解不夠多的朋友,建議深入學習一下相關的知識。

理解了這些知識之后,相信對於上面的Button組件所涉及到的東西也就能夠非常清楚知道是怎么回事了。接下來,我們需要創建一個彈窗組件,Dialog.jsx

 

 

這個組件沒有太多特別的東西,唯一需要關注的一點是,我們也可以通過props傳遞一個函數給子組件。例如這里的close方法。該方法在父組件中定義,但是卻在子組件Dialog中執行,他的作用是關閉彈窗。

我們很容易知道父組件想要修改子組件,只需要通過改變傳入的props屬性即可。那么子組件想要修改父組件的狀態呢?正是父組件通過向子組件傳遞一個函數的方式來改變。

該函數在父組件中定義,在子組件中執行。而函數的執行內容,則是修改父組件的狀態。這就是close的原理,我們來看看父組件中是如何處理這些邏輯的。

創建一個父組件App.jsx

App組件的state中,loading用於判斷Button按鈕是否顯示loading圖標,dialog用於判斷是否需要顯示彈窗,message則是表示彈窗的提示內容。

我們自定義的鈎子函數submitclose則分別是與子組件Button與Dialog交互的一個橋梁。前面我們說過了,想要在子組件中改變父級的狀態,就需要通過在父組件中創建鈎子函數,並傳遞給子組件執行的方式來完成。

在App.jsx中我們還看到代碼中引入了一個css文件。這是構建工具幫助我們整合的方式,我們可以直接將css文件當做一個單獨的模塊引入進來。我們還可以通過同樣的方式引入圖片等資源。

style.css也是在src目錄下創建的。

最后修改index.js,即可將程序運行起來。

 

點擊之后loading出現

1s之后得到結果,提示框出現

那么總結一下組件之間的交互。

父組件改變子組件,通過改變傳入的props屬性值即可。
而子組件改變父組件的狀態,則需要在父組件中創建鈎子函數,然后讓鈎子函數通過props傳遞給子組件,並在子組件中執行。

那么子組件與子組件之間的交互方式,也就是通過影響共同的父組件來進行交互的。正如我們這個例子中的點擊按鈕,出現彈窗一樣。這就是react組件之間交互的核心。

異步組件

在學習異步組件之前,可能還需要大家去折騰一下如何禁用瀏覽器的跨域限制。禁用跨域限制可以讓我們使用更多的公共api進行學習,但是很多人並不知道還可以這樣玩。總之一句話,知道了如何禁用瀏覽器的跨域限制,會讓你的學習速度提升很多,很多項目你就可以動手自己嘗試了。

我這里只能提供在mac環境下如何禁用chrome瀏覽器的跨域限制。在命令行工具中輸入以下指令啟動chrome即可。

 

啟動成功之后會有這樣的提示

在safari瀏覽器中則更加簡單。

開發 -> 停用跨源限制

windows環境下如何做需要大家自己去研究。

OK,禁用跨域限制以后,我們就可以自如的請求別人的接口。這個時候再來學習異步組件就能輕松很多。

異步組件並不是那么復雜,由於接口請求會經歷一點時間,因此在組件第一次渲染的時候,並不能直接將我們想要的數據渲染完成,那么就得再接口請求成功之后,重新渲染一次組件。上面的知識已經告訴大家,通過使用this.setState修改state的值可以達到重新渲染的目的。

所以我們通常的做法就是在接口請求成功之后,使用this.setState

為了降低學習難度,我們暫時先使用jquery中提供的方法來請求數據。

目前比較常用的是axios

首先在我們的項目中,安裝jquery庫。我們通常都會使用這樣的方式來安裝新的組件和庫。

然后在src目錄下創建一個News.jsx,借助知乎日報的api,我們來嘗試完成一個簡單的異步組件。

 

 

style.css中簡單補上相關的css樣式

並在App.jsx中引入使用即可。

 

組件運行結果展示

這個組件除了獲取數據,沒有額外的邏輯處理,但仍然有幾個需要非常注意的地方。

1、 若非特殊情況,盡量保證數據請求的操作在componentDidMount中完成。

2、 react中的列表渲染通常通過調用數組的原生方法map方法來完成,具體使用方式可參考上例。

3、為了確保性能,被渲染的每一列都需要給他配置一個唯一的標識,正入上栗中的key={i}。我們來假想一個場景,如果我們在數組的最前面新增一條數據,如果沒有唯一的標識,那么所有的數據都會被重新渲染,一旦數據量過大,這會造成嚴重的性能消耗。唯一標識會告訴react,這些數據已經存在了,你只需要渲染新增的那一條就可以了。

4、如果你想要深入了解該組件的具體變化,你可以在render方法中,通過console.log(this.state)的方式,觀察在整個過程中,組件渲染了多少次,已經每一次this.state中的具體值是什么,是如何變化的。

高階組件

很多人寫文章喜歡把問題復雜化,因此當我學習高階組件的時候,查閱到的很多文章都給人一種高階組件高深莫測的感覺。但是事實上卻未必。我們常常有一些口頭俗語,比如說“包一層”就是可以用來簡單解釋高階組件的。在普通組件外面包一層邏輯,就是高階組件。

在進一步學習高階組件之前,我們來回顧一下new與構造函數之間的關系。在前面我有文章提到過為什么構造函數中this在運行時會指向new出來的實例,不知道還有沒有人記得。我將那段代碼復制過來。

在上面的例子中,首先我們定義了一個本質上與普通函數沒區別的構造函數,然后將該構造函數作為參數傳入New函數中。我在New函數中進行了一些的邏輯處理,讓New函數的返回值為一個實例,正因為New的內部邏輯,讓構造函數中的this能夠指向返回的實例。這個例子就是一個“包一層”的案例。

再來看一個簡單的例子:

 

 

在上面的例子中,我們把html的DIV標簽作為基礎元件。對他新增了一個輸出一條提示信息的能力。而新的Div組件,就可以理解為div標簽的高階組件。所以到這里希望大家已經理解了包一層的具體含義。

react組件的高階組件,就是在基礎react組件外面包一層,給該基礎組件賦予新的能力。

OK,我們來試試定義第一個高階組件,該高階組件的第一個能力,就是向基礎組件中傳入一個props參數。

在例子中,傳入的參數可能沒有任何實際意義,但是在實際開發中,我們可以傳入非常有必要的參數來簡化我們的代碼和邏輯。

先來定義一個擁有上述能力的高階組件

盡管這個高階組價足夠簡單,但是他已經呈現了高階組件的定義方式。現在我們在一個基礎組件中來使用該高階組件。

 

 

我們看到其實在基礎組件中,對外拋出的接口是Addsss(Basic),這是高階組件里定義的函數運行的結果。也就是說,其實基礎組件中返回的是高階組件中定義的Asss中間組件。這和new的思路幾乎完全一致。

當然,想要理解,並熟練使用高階組件並不是一件容易的事情,大家初學時也不用非要完全掌握他。當你對react慢慢熟練之后,你可以嘗試使用高階組件讓自己的代碼更加靈活與簡練。這正是向函數式編程思維轉變的一個過程。

在進步學習的過程中,你會發現無論是路由組件react-router,或者react-redux都會使用高階組件來實現一些功能。只要你遇到他們的時候,你能明白,哦,原來是這么回事兒就行了。

react路由

react提供了react-router組件來幫助我們實現路由功能。

但是react-router是一個不太好講的知識點。因為由於react-router 4進行了顛覆性的更新,導致了react-router 3與react-router 4的使用方式大不一樣。也正是由於變化太大,所以很多項目仍然正在使用react-router3,並且沒有過渡到react-router4的打算。

因此這里我就不多講,提供一些參考學習資料。

未完待續

由於時間關系,暫時就只能寫到這里了。
本來還寫了一個比較完整的例子也在這篇文章里逐步分析如何實現的,但是時間確實不夠。所以如果覺得看了上面的知識還想進一步學習的話,可以先去https://github.com/yangbo5207/advance15 看看這個完整例子的樣子。

另外我曾經寫了一篇如何快速掌握一門前端框架,希望大家可以參考參考。

按照我的計划,只要理解了上面我所提到的知識,並把我准備的這個完整例子理解了。那么你的react掌握程度也算是小有所成了。至少應屆畢業生找工作能提到這些思維方式應該會很有幫助。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM