React簡介
首先不能否認React.js是全球最火的前端框架(Facebook推出的前端框架),國內的一二線網際網路公司大部分都在使用React進行開發,比如阿里、美團、百度、去哪兒、網易 、知乎這樣的一線網際網路公司都把React作為前端主要技術棧。
React的社群也是非常強大的,隨著React的普及也衍生出了更多有用的框架,比如ReactNative和React VR。React從13年開始推廣,現在已經推出16RC(React Fiber)這個版本,效能和易用度上,都有很大的提升。
React優點總結
- 生態強大:現在沒有哪個框架比React的生態體系好的,幾乎所有開發需求都有成熟的解決方案。
- 上手簡單: 你甚至可以在幾個小時內就可以上手React技術,但是他的知識很廣,你可能需要更多的時間來完全駕馭它。
- 社群強大:你可以很容易的找到志同道合的人一起學習,因為使用它的人真的是太多了。
需要的前置知識
-
JavaScript基礎:如果能會ES6就更好了
-
npm基礎:你需要會使用npm的包管理
React開發環境搭建
- 安裝Node只需要進入Node網站,進行響應版本的下載,然後進行雙擊安裝就可以了。
// 安裝完成開啟命令視窗輸入
node -v //出現版本號則安裝成功
複製程式碼
- 腳手架的安裝
// 安裝react的腳手架工具
//create-react-app是React官方出的腳手架工具
npm install -g create-react-app
複製程式碼
- 建立一個React專案
// 桌面建立一個react-demo的資料夾
// 進入當前資料夾,開啟命令列
create-react-app demo //用腳手架建立React專案
npm start // 安裝完成進入demo資料夾啟動專案
複製程式碼
專案根目錄中的檔案介紹
-
README.md :這個檔案主要作用就是對專案的說明,已經預設寫好了一些東西,你可以簡單看看。如果是工作中,你可以把檔案中的內容刪除,自己來寫這個檔案,編寫這個檔案可以使用Markdown的語法來編寫。
-
package.json: 這個檔案是webpack配置和專案包管理檔案,專案中依賴的第三方包(包的版本)和一些常用命令配置都在這個裡邊進行配置,當然腳手架已經為我們配置了一些了,目前位置,我們不需要改動。如果你對webpack瞭解,對這個一定也很熟悉。
-
package-lock.json:這個檔案用一句話來解釋,就是鎖定安裝時的版本號,並且需要上傳到git,以保證其他人再npm install 時大家的依賴能保證一致。
-
gitignore: 這個是git的選擇性上傳的配置檔案,比如一會要介紹的node_modules資料夾,就需要配置不上傳。
-
node_modules:這個資料夾就是我們專案的依賴包,到目前位置,腳手架已經都給我們下載好了,你不需要單獨安裝什麼。
-
public:公共檔案,裡邊有公用模板和圖示等一些東西。
-
src: 主要程式碼編寫檔案,這個資料夾裡的檔案對我們來說最重要,都需要我們掌握。
public資料夾介紹
這個檔案都是一些專案使用的公共檔案,也就是說都是共用的
-
favicon.ico: 這個是網站或者說專案的圖示,一般在瀏覽器標籤頁的左上角顯示。
-
index.html: 首頁的模板檔案
-
mainifest.json:移動端配置檔案
src資料夾介紹
這個目錄裡邊放的是我們開放的原始碼,我們平時操作做最多的目錄。
-
index.js: 這個就是專案的入口檔案
-
index.css:這個是index.js裡的CSS檔案。
-
app.js: 這個檔案相當於一個方法模組,也是一個簡單的模組化程式設計。
-
serviceWorker.js:這個是用於寫移動端開發的,PWA必須用到這個檔案,有了這個檔案,就相當於有了離線瀏覽的功能。
元件的介紹
入口檔案的編寫
寫一個專案的時候一般要從入口檔案進行編寫的,在src目錄下,index.js檔案就是入口檔案
import React from 'react' // 引入react
import ReactDOM from 'react-dom' // 引入react-dom
import App from './App' // 引入App模組
ReactDOM.render(<App />,document.getElementById('root')) // 將App模組渲染到了 root ID上面
複製程式碼
App元件的編寫
import React from 'react'
// JSX語法
class App extends React.Component{
render(){
return (
<div>
我是APP元件
</div>
)
}
}
export default App;
複製程式碼
React中JSX語法簡介
JSX就是Javascript和XML結合的一種格式。React發明了JSX,
可以方便的利用HTML語法來建立虛擬DOM,當遇到<,JSX就當作HTML解析,
遇到{就當JavaScript解析.
複製程式碼
元件和普通JSX語法區別
這個說起來也只有簡單的一句話,就是你自定義的元件必須首寫字母要進行大寫,而JSX是小寫字母開頭的。
JSX中使用三元運算子
在JSX中也是可以使用js語法的
import React from 'react'
// JSX語法
class App extends React.Component{
render(){
return (
<div>
<div>{false ? '不顯示我' : '顯示的我'}</div>
我是APP元件
</div>
)
}
}
export default App;
複製程式碼
元件外層包裹原則
react和vue元件模板的原則一樣,最外層必須有且只有一個元素,多了會報錯
下面這個列子就是一個錯誤的,因為最外層有了兩個元素
import React from 'react'
// JSX語法
class App extends React.Component{
render(){
return (
<div></div>
<div>
<div>{false ? '不顯示我' : '顯示的我'}</div>
我是APP元件
</div>
)
}
}
export default App;
複製程式碼
Fragment標籤
加上最外層的DIV,元件就是完全正常的,但是你的佈局就偏不需要這個最外層的標籤怎麼辦?比如我們在作Flex佈局的時候,外層還真的不能有包裹元素。這種矛盾其實React16已經有所考慮了,為我們準備了標籤。
import React from 'react'
// JSX語法
class App extends React.Component{
render(){
return (
<React.Fragment>
<div>{false ? '不顯示我' : '顯示的我'}</div>
</React.Fragment>
)
}
}
export default App;
複製程式碼
這時候再去瀏覽器的Elements中檢視,就會發現已經沒有外層的包裹了。
響應式設計和資料的繫結
React不建議你直接操作DOM元素,而是要通過資料進行驅動,改變介面中的效果。React會根據資料的變化,自動的幫助你完成介面的改變。所以在寫React程式碼時,你無需關注DOM相關的操作,只需要關注資料的操作就可以了(這也是React如此受歡迎的主要原因,大大加快了我們的開發速度)。
import React from 'react'
// JSX語法
class App extends React.Component{
constructor(props){
super(props) //呼叫父類的建構函式,固定寫法
this.state={
myName: '只會番茄炒蛋',
list: ['番茄', '炒蛋']
}
}
render(){
return (
<React.Fragment>
<div>{this.state.myName}</div>
<ul>
{
this.state.list.map((item,index) => {
return (
<li key={item + index}>{item}</li>
)
})
}
</ul>
</React.Fragment>
)
}
}
export default App;
複製程式碼
繫結事件
import React from 'react'
// JSX語法
class App extends React.Component{
constructor(props){
super(props) //呼叫父類的建構函式,固定寫法
this.state={
myName: '只會番茄炒蛋',
list: ['番茄', '炒蛋']
}
this.changeBtn = this.changeBtn.bind(this)
}
render(){
return (
<React.Fragment>
<div>{this.state.myName}</div>
<button onClick={this.changeBtn}>點選事件</button>
</React.Fragment>
)
}
changeBtn () {
// 這裡要注意,如果沒有繫結this這裡的this是undefined
// 通過setState方法去改變資料,保證頁面會渲染改變後的內容
this.setState({
myName: '我的點選按鈕後被改變的值'
})
}
}
export default App;
複製程式碼
JSX防踩坑的幾個地方
JSX程式碼註釋
以下兩種方式書寫程式碼註釋
{/* 正確註釋的寫法 */}
{ // 正確註釋的寫法 }
複製程式碼
JSX中的class陷阱
它是防止和js中的class類名衝突, 所以JSX中都是用className
<input class="input"/> // 錯誤的寫法
<input className="input"/> // 正確的寫法
複製程式碼
JSX中的html解析問題
如果想在文字框裡輸入一個h1標籤,並進行渲染。預設是不會生效的,只會把h1標籤列印到頁面上,這並不是我想要的。如果工作中有這種需求,可以使用dangerouslySetInnerHTML屬性解決。具體程式碼如下:
<li dangerouslySetInnerHTML={{__html:item}}> {<h1>我會變成h1號字型</h1>}</li>
複製程式碼
JSX中
JSX中label的坑,也算是比較大的一個坑,label是html中的一個輔助標籤,也是非常有用的一個標籤。
<div>
<label>加入服務:</label>
<input className="input" value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button onClick={this.addList.bind(this)}> 增加服務 </button>
</div>
複製程式碼
這時候想點選“加入服務”直接可以啟用文字框,方便輸入。按照html的原思想,是直接加ID就可以了。程式碼如下:
<div>
<label for="jspang">加入服務:</label>
<input id="jspang" className="input" value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button onClick={this.addList.bind(this)}> 增加服務 </button>
</div>
複製程式碼
這時候你瀏覽效果雖然可以正常,但console裡還是有紅色警告提示的。大概意思是不能使用for.它容易和javascript裡的for迴圈混淆,會提示你使用htmlfor。
<div>
<label htmlFor="jspang">加入服務:</label>
<input id="jspang" className="input" value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button onClick={this.addList.bind(this)}> 增加服務 </button>
</div>
複製程式碼
元件的拆分
父元件如何使用子元件
// 子元件
import React from 'react'
// JSX語法
class childItem extends React.Component{
return (
<React.Fragment>
<div>我是子元件</div>
</React.Fragment>
)
}
export default childItem;
複製程式碼
// 父元件
import React from 'react'
// 引入子元件
import childItem from './childItem'
// JSX語法
class parentItem extends React.Component{
return (
<React.Fragment>
{/* 使用了子元件 */}
<childItem/>
</React.Fragment>
)
}
export default parentItem;
複製程式碼
父子元件的傳值
父元件通過自定義屬性將要傳遞的值傳遞給子元件
// 父元件
import React from 'react'
// 引入子元件
import childItem from './childItem'
// JSX語法
class parentItem extends React.Component{
constractor (props) {
super(props)
this.state = {
myName: '只會番茄炒蛋'
}
}
return (
<React.Fragment>
{/* 使用了子元件 */}
<childItem myName={this.state.myName}/>
</React.Fragment>
)
}
export default parentItem;
複製程式碼
子元件通過this.props.XXX接受父元件傳遞迴來的值
// 子元件
import React from 'react'
// JSX語法
class childItem extends React.Component{
return (
<React.Fragment>
<div>{this.props.myName}</div>
</React.Fragment>
)
}
export default childItem;
複製程式碼
父元件向子元件傳遞內容,靠屬性的形式傳遞。
子元件向父元件傳遞資料
切記單項資料流!!!
React有明確規定,子元件時不能操作父元件裡的資料的,所以需要藉助一個父元件的方法,來修改父元件的內容。
// 子元件
import React from 'react'
// JSX語法
class childItem extends React.Component{
constructor (props) {
super(props)
this.changeParent = this.changeParent.bind(this)
}
return (
<React.Fragment>
<div onClick={this.changeParent}>{this.props.myName}</div>
</React.Fragment>
)
changeParent () {
// 呼叫父元件傳遞過來的方法
this.props.pranentChange()
}
}
export default childItem;
複製程式碼
// 父元件
import React from 'react'
// 引入子元件
import childItem from './childItem'
// JSX語法
class parentItem extends React.Component{
constractor (props) {
super(props)
this.state = {
myName: '只會番茄炒蛋'
}
this.pranentChange = this.pranentChange.bind(this)
}
return (
<React.Fragment>
{/* 使用了子元件 */}
<childItem
pranentChange={this.pranentChange}
myName={this.state.myName}
/>
</React.Fragment>
)
pranentChange () {
this.setState({
myName: '番茄炒蛋少放糖'
})
}
}
export default parentItem;
複製程式碼
PropTypes校驗傳遞值
在父元件向子元件傳遞資料時,使用了屬性的方式,也就是props,但是沒有任何的限制。這在工作中時完全不允許的,因為大型專案,如果你不校驗,後期會變的異常混亂,業務邏輯也沒辦法保證。
PropTypes的應用
普通效驗
// 子元件
import React from 'react'
// 引入效驗
import PropTypes from 'prop-types'
// JSX語法
class childItem extends React.Component{
constructor (props) {
super(props)
this.changeParent = this.changeParent.bind(this)
}
return (
<React.Fragment>
<div onClick={this.changeParent}>{this.props.myName}</div>
</React.Fragment>
)
changeParent () {
// 呼叫父元件傳遞過來的方法
this.props.pranentChange()
}
}
childItem.prorTypes = {
myName: PropTypes.string, // 效驗傳入的內容必須是一個字串
pranentChange: PropTypes.func // 效驗傳入的內容必須是一個function
}
export default childItem;
複製程式碼
注意: 這裡新增效驗以後,如果不按照效驗規則傳入內容會有warning警告
必傳值的效驗---isRequired
例如這裡加了一個newName的屬性,並且放入JSX中,就算父元件不傳遞這個值也不會報錯的
// 子元件
render() {
return (
<div >{this.props.newName}</div>
);
}
複製程式碼
但是怎樣避免必須傳遞newName這個屬性值?如果不傳遞就報錯,這就需要使用isRequired關鍵字了,它表示必須進行傳遞,如果不傳遞就報錯。
childItem.prorTypes = {
// 效驗傳入的內容必須是一個字串並且必須傳入值
newName:PropTypes.string.isRequired,
}
複製程式碼
使用預設值---defaultProps
有時候子元件是需要有一個預設的值,如果父元件不傳就用預設的,如果傳了就用父元件傳遞過來的值,defalutProps就可以實現預設值的功能,比如現在把newName的預設值設定成"只會番茄炒蛋" 。
childItem.defaultProps = {
// 子元件使用父元件傳遞的值,但是他自己有個預設的值
newName:'只會番茄炒蛋'
}
複製程式碼
ref的使用方法
在編寫元件中的方法時,經常會遇到語義化很模糊的程式碼,這對於團隊開發是一個很大的問題。因為review程式碼或者合作時都會影響開發效率。或者到這核心成員離開,專案倒閉的嚴重影響。所以我們必須重視react程式碼當中的語義化。ref是個不錯的工具
import React from 'react'
// JSX語法
class parentItem extends React.Component{
constractor (props) {
super(props)
this.state = {
myName: '只會番茄炒蛋'
}
this.inputChange = this.inputChange.bind(this)
}
return (
<React.Fragment>
<input
value={this.state.myName}
onChange={this.inputChange}
></input>
</React.Fragment>
)
inputChange (e) {
console.log(e.target.value)
}
}
export default parentItem;
複製程式碼
想要獲取上面input輸入的值,必須通過e.target.value,這樣並不直觀,也不好看,這中情況可以使用ref來進行解決
import React from 'react'
// JSX語法
class parentItem extends React.Component{
constractor (props) {
super(props)
this.state = {
myName: '只會番茄炒蛋'
}
this.inputChange = this.inputChange.bind(this)
}
return (
<React.Fragment>
<input
value={this.state.myName}
onChange={this.inputChange}
ref={input => {this.input = input}}
></input>
</React.Fragment>
)
inputChange (e) {
console.log(this.input.value)
}
}
export default parentItem;
複製程式碼
這就使程式碼變得語義化和優雅的多。但是是不建議用ref這樣操作的,因為React的是資料驅動的,所以用ref會出現各種問題。
ref使用中的坑
比如現在我們要用ref繫結獲取子元素的數量,可以先用ref進行繫結。
<ul ref={(ul)=>{this.ul=ul}}>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
複製程式碼
這時候如果我們動態新增或者減少li的數量,並在方法中列印li的數量,發現返回的數量並不準確,這個坑是因為React中更新setState是一個非同步函式所造成的。也就是這個setState在程式碼執行是有一個時間的,如果你真的想了解清楚,你需要對什麼是虛擬DOM有一個瞭解。簡單的說,就是因為是非同步,還沒等虛擬Dom渲染,我們的console.log就已經執行了。
那這個程式碼怎麼編寫才會完全正常那,其實setState方法提供了一個回撥函式,也就是它的第二個函式。下面這樣寫就可以實現我們想要的方法了。
增加/刪除(){
this.setState({
list:改變後的資料,
},()=>{
console.log(this.ul.querySelectorAll('li').length)
})
}
複製程式碼
生命週期
什麼是生命週期函式
生命週期函式指在某一個時刻元件會自動呼叫執行的函式
複製程式碼
掛載
當元件例項被建立並插入 DOM 中時,其生命週期呼叫順序如下:
- constructor()
如果不初始化 state 或不進行方法繫結,則不需要為 React 元件實現建構函式。
在 React 元件掛載之前,會呼叫它的建構函式。在為 React.Component 子類實現建構函式時,
應在其他語句之前前呼叫 super(props)。否則,this.props 在建構函式中可能會出現未定義的 bug。
通常,在 React 中,建構函式僅用於以下兩種情況:
* 通過給 this.state 賦值物件來初始化內部 state。
* 為事件處理函式繫結例項
在 constructor() 函式中不要呼叫 setState() 方法。
如果你的元件需要使用內部 state,請直接在建構函式中為 this.state 賦值初始 state:
複製程式碼
- static getDerivedStateFromProps()
getDerivedStateFromProps 會在呼叫 render 方法之前呼叫,並且在初始掛載及後續更新時都會被呼叫。
它應返回一個物件來更新 state,如果返回 null 則不更新任何內容。
複製程式碼
- render()
頁面state或props發生變化時執行。
複製程式碼
- componentDidMount()
元件掛載完成時被執行。一般也在這裡發起網路請求
複製程式碼
更新
當元件的 props 或 state 發生變化時會觸發更新。元件更新的生命週期呼叫順序如下:
- static getDerivedStateFromProps()
// 不常用的生命週期方法
getDerivedStateFromProps 會在呼叫 render 方法之前呼叫,並且在初始掛載及後續更新時都會被呼叫。
它應返回一個物件來更新 state,如果返回 null 則不更新任何內容。
複製程式碼
- shouldComponentUpdate()
// 不常用的生命週期方法
根據 shouldComponentUpdate() 的返回值,判斷 React 元件的輸出是否受當前 state 或 props 更改的影響。
預設行為是 state 每次發生變化元件都會重新渲染。大部分情況下,你應該遵循預設行為。
複製程式碼
- render()
render() 方法是 class 元件中唯一必須實現的方法。
當 render 被呼叫時,它會檢查 this.props 和 this.state 的變化
複製程式碼
- getSnapshotBeforeUpdate()
// 不常用的生命週期方法
getDerivedStateFromProps 會在呼叫 render 方法之前呼叫,並且在初始掛載及後續更新時都會被呼叫。
它應返回一個物件來更新 state,如果返回 null 則不更新任何內容。
複製程式碼
- componentDidUpdate()
componentDidUpdate() 會在更新後會被立即呼叫。首次渲染不會執行此方法。
複製程式碼
解除安裝
當元件從 DOM 中移除時會呼叫如下方法:
- componentWillUnmount()
componentWillUnmount() 會在元件解除安裝及銷燬之前直接呼叫。在此方法中執行必要的清理操作,
例如,清除 timer,取消網路請求或清除在 componentDidMount() 中建立的訂閱等。
複製程式碼
錯誤處理
當渲染過程,生命週期,或子元件的建構函式中丟擲錯誤時,會呼叫如下方法:
- static getDerivedStateFromError()
// 不常用的生命週期方法
此生命週期會在後代元件丟擲錯誤後被呼叫。 它將丟擲的錯誤作為引數,並返回一個值以更新 state
複製程式碼
- componentDidCatch()
// 不常用的生命週期方法
componentDidCatch() 會在“提交”階段被呼叫,因此允許執行副作用。 它應該用於記錄錯誤之類的情況:
複製程式碼
React中的axios資料請求
安裝axios
npm install axios -S
複製程式碼
使用
// 那個元件使用在那個頁面引入
import axios from 'axios'
複製程式碼
引入後,可以在componentDidMount生命週期函式裡請求ajax,我也建議在componentDidMount函式裡執行,因為在render裡執行,會出現很多問題,比如一直迴圈渲染;在componentWillMount裡執行,在使用RN時,又會有衝突。所以強烈建議在componentDidMount函式裡作ajax請求。
componentDidMount(){
axios.post('https://www.easy-mock.com/mock/5d50245e710c4d0d04d78d19/echart')
.then((res)=>{console.log('axios 獲取資料成功:'+JSON.stringify(res)) })
.catch((error)=>{console.log('axios 獲取資料失敗'+error)})
}
複製程式碼
動畫react-transition-group
React有著極好的開發生態,開發需要的任何基本需求都可以找到官方或大神造的輪子,動畫這種必不可少的東西當然也不例外,React生態中有很多第三方的動畫元件,學習一下react-transition-group動畫元件。可以滿足日常動畫開發需求。 推薦的最重要理由是:這個也是react官方提供的動畫過渡庫,有著完善的API文件)。
安裝react-transition-group
npm install react-transition-group -S
複製程式碼
安裝好後,你可以先去github上來看一下文件,他是有著三個核心庫(或者叫元件)。
- Transition
- CSSTransition
- TransitionGroup
使用CSSTransition
先用import進行引入,程式碼如下:
import { CSSTransition } from 'react-transition-group'
複製程式碼
引入後便可以使用了,使用的方法就和使用自定義元件一樣,直接寫,而且不再需要管理className了,這部分由CSSTransition進行管理。
render() {
return (
<div>
<CSSTransition
in={this.state.isShow} //用於判斷是否出現的狀態
timeout={2000} //動畫持續時間
classNames="boss-text" //className值,防止重複
>
<div>BOSS級人物-孫悟空</div>
</CSSTransition>
<div><button onClick={this.toToggole}>召喚Boss</button></div>
</div>
);
}
複製程式碼
需要注意的是classNames這個屬性是由s的,如果你忘記寫,會和原來的ClassName混淆出錯,這個一定要注意。
- xxx-enter: 進入(入場)前的CSS樣式;
- xxx-enter-active:進入動畫直到完成時之前的CSS樣式;
- xxx-enter-done:進入完成時的CSS樣式;
- xxx-exit:退出(出場)前的CSS樣式;
- xxx-exit-active:退出動畫知道完成時之前的的CSS樣式。
- xxx-exit-done:退出完成時的CSS樣式。
.input {border:3px solid #ae7000}
.boss-text-enter{
opacity: 0;
}
.boss-text-enter-active{
opacity: 1;
transition: opacity 2000ms;
}
.boss-text-enter-done{
opacity: 1;
}
.boss-text-exit{
opacity: 1;
}
.boss-text-exit-active{
opacity: 0;
transition: opacity 2000ms;
}
.boss-text-exit-done{
opacity: 0;
}
複製程式碼
unmountOnExit 屬性
CSSTransition加上unmountOnExit屬性,加上這個的意思是在元素退場時,自動把DOM也刪除,這是以前用CSS動畫沒辦法做到的。
render() {
return (
<div>
<CSSTransition
in={this.state.isShow} //用於判斷是否出現的狀態
timeout={2000} //動畫持續時間
classNames="boss-text" //className值,防止重複
unmountOnExit
>
<div>BOSS級人物-孫悟空</div>
</CSSTransition>
<div><button onClick={this.toToggole}>召喚Boss</button></div>
</div>
);
}
複製程式碼
使用TransitionGroup
它就是負責多個DOM元素的動畫的,我們還是拿小姐姐這個案例作例子,現在可以新增任何的服務專案,但是都是直接出現的,沒有任何動畫,現在就給它新增上動畫。新增動畫,先引入transitionGrop。
import {CSSTransition , TransitionGroup} from 'react-transition-group'
複製程式碼
引入之後,就可以使用這個元件了,方法是在外層增加標籤。
<ul ref={(ul)=>{this.ul=ul}}>
<TransitionGroup>
<li>1</li>
<li>2</li>
<li>3</li>
</TransitionGroup>
</ul>
複製程式碼
但是隻有這個是不夠的,你還是需要加入,來定義動畫。
<ul ref={(ul)=>{this.ul=ul}}>
<TransitionGroup>
<CSSTransition
timeout={1000}
classNames='boss-text'
unmountOnExit
appear={true}
key={index+item}
>
<li>1</li>
</CSSTransition>
<CSSTransition
timeout={1000}
classNames='boss-text'
unmountOnExit
appear={true}
key={index+item}
>
<li>2</li>
</CSSTransition>
</TransitionGroup>
</ul>
複製程式碼
React動畫還有很多知識,能做出很多酷炫的效果,完全可以單獨分出來一個崗位,我在工作中用的都是比較簡單的動畫,用react-transition-group動畫已經完全可以滿足我的日常開發需求了
以上大部分內容和講解都來來自技術胖的部落格,結合了自己對react的理解。