react项目中的参数解构_一天入门React学习心得
一天入門React學(xué)習(xí)心得
閱讀前必讀
本文寫(xiě)的倉(cāng)促,算是一個(gè)學(xué)習(xí)筆記吧,算是一個(gè)入門級(jí)的學(xué)習(xí)文章。如果你剛剛?cè)腴T,那么可能一些入門的視頻可能更加適合你。但如果具備一些知識(shí),比如Vue,那么視頻就不適合了。建議看完本篇文章在腦海中過(guò)一遍映像,在去官網(wǎng)深讀,和一些深入文章,想來(lái)會(huì)有非常好的提升。
“一個(gè)框架不是看幾篇文章,寫(xiě)寫(xiě)Demo就能說(shuō)自己會(huì),熟悉。需要不斷實(shí)踐,踩坑,學(xué)習(xí)原理。多想才能掌握。我只是結(jié)合Vue進(jìn)行的React學(xué)習(xí),只是冰山一角罷了。充其量只是API的搬運(yùn)工。
- - QAQ初始化項(xiàng)目
新手還是推薦官方的腳手架,通過(guò)npx來(lái)進(jìn)行項(xiàng)目的初始化一個(gè)demo項(xiàng)目。
npx?create-react-app?項(xiàng)目名稱默認(rèn)生成的目錄情況下,項(xiàng)目的解構(gòu)就是這樣的。
Mode????????????????LastWriteTime?????????Length?Name----????????????????-------------?????????------?----
d-----??????????20.6.15?????14:21????????????????public
d-----??????????20.6.15?????16:41????????????????src
-a----??????????20.6.15?????14:21????????????310?.gitignore
-a----??????????20.6.15?????14:22????????????746?package.json
-a----??????????20.6.15?????14:21???????????2884?README.md
-a----??????????20.6.15?????14:22?????????526017?yarn.lock
隨后通過(guò)npm 或者 yarn 來(lái)將項(xiàng)目跑起來(lái)。執(zhí)行shell后會(huì)自動(dòng)打開(kāi)一個(gè)瀏覽器,當(dāng)看到localhost:3000渲染后。那么就可以開(kāi)啟React大門了
#??npm?shell?命令npm?run?start
#?yarn?shell?命令
yarn?start
React元素渲染-JSX
在Vue中template模板得到大量的使用,只要你會(huì)寫(xiě)HTML那么應(yīng)該難不倒你這個(gè)小機(jī)靈鬼。而React則是使用了在函數(shù)中直接返回DOM。看起來(lái)非常的神奇,也導(dǎo)致了一些小伙伴在入門的時(shí)候會(huì)有點(diǎn)摸不著頭腦,但是如果有一定基礎(chǔ),在Vue中寫(xiě)過(guò)了Render 函數(shù)的話,我想上手起來(lái)還是非常容易的。它看起來(lái)是下面這個(gè)樣子的。其本質(zhì)上就是一個(gè)createElement的過(guò)程。所以,將這種模板的渲染方式稱之為JSX。
import?React?from?'react';import?'./App.css';
function?App()?{
??return?(
????<div?className="App"><h1>你好呀h1><p>今天又是充滿希望的一天...p>div>
??);
}
export?default?App;
通過(guò)React的JSX模板引擎,最終將其渲染到DOM上
變量綁定
在Vue的模板中,通過(guò){{}}兩個(gè)花括號(hào)來(lái)聲明約束,表示這個(gè)聲明中的字段是一個(gè)js的值,而不是一個(gè)文本。在React則是使用了{(lán)}一個(gè)花括號(hào)來(lái)做約定。那么就可以在DOM中使用js了。下面是一個(gè)Class組件,將state的text值綁定在DOM的。
class?App?extends?React.Component?{??constructor?(props)?{
????super(props)
????this.state?=?{
??????text:?'我是wangly19'
????}
??}
??updateText?()?{
????this.setState({
??????text:?'我是帥氣的wangly19'
????})
??}
??render?()?{
????return?(
??????<div?className="App"><p>我是一個(gè)動(dòng)態(tài)的數(shù)據(jù):?{this.state.text}p><button?onClick={?this.updateText.bind(this)?}>更換button>div>
????)
??}
}
結(jié)果
條件渲染
在Vue中,如果需要?jiǎng)討B(tài)的渲染一個(gè)節(jié)點(diǎn),是通過(guò)v-if指令來(lái)實(shí)現(xiàn)的,在React中呢,可以使用運(yùn)算符來(lái)渲染元素。通過(guò)Vue來(lái)做一個(gè)對(duì)比吧。
“通過(guò)&&(或)運(yùn)算符來(lái)達(dá)到v-if的一樣效果。
- - QAQrender?()?{??return?(
????<div?className="App"><p>我是一個(gè)動(dòng)態(tài)的數(shù)據(jù):?{this.state.text}p>
??????{/*?{?<p?v-if="true">2p>?}?*/}
??????{true?&&?<p>2p>}div>
??)
}
“
通過(guò)三元運(yùn)算符可以來(lái)達(dá)到v-if和v-else一樣的效果。
- - QAQrender?()?{??return?(
????<div?className="App"><p>我是一個(gè)動(dòng)態(tài)的數(shù)據(jù):?{this.state.text}p>
??????{/*?{?<p?v-if="true">2p>?}?*/}
??????{true???<p>truep>?:?<p>falsep>}div>
??)
}
列表渲染
通過(guò)map方法來(lái)遍歷一些基本數(shù)據(jù)結(jié)構(gòu)的節(jié)點(diǎn)。
“通過(guò)數(shù)據(jù)結(jié)構(gòu)自帶的map可以遍歷出value,index,key 在return中返回節(jié)點(diǎn)信息。
- - QAQ事件處理
在JavaScript中,通過(guò)onClick來(lái)綁定一個(gè)事件。
<button?onclick="activeBuff">激活按鈕button>而在jsx中,則是通過(guò)onClick屬性,且后面加一個(gè)jsx渲染模板的方式。
“需要注意的是,Class組件下的this是不存在的,需要用戶手動(dòng)為方法綁定this,在調(diào)用的點(diǎn)擊事件方法。
- - QAQthis.activeBuff.bind(this)?}>激活按鈕</button>組件
眾所周知,Vue和React都是組件化解決方案,那么在React中是如何創(chuàng)建一個(gè)組件的呢?在React新版本中,推出了React Hooks方案。所以現(xiàn)在主流的還是Class組件和Function組件。
Class組件
Class組件的創(chuàng)建方式非常的簡(jiǎn)單,只需要?jiǎng)?chuàng)建一個(gè)Class類并且讓它繼承React.Component,在Render方法中return出JSX的模板。
同時(shí)通過(guò)構(gòu)造函數(shù),處理Props。并且聲明state狀態(tài)初始化一個(gè)對(duì)象,將Props掛載到super上。
class?App?extends?React.Component?{??constructor?(props)?{
????super(props)
????this.state?=?{
????}
??}
??//?render函數(shù)
??render?()?{
????return?(
??????<div?className="App"><p>我是Class組件p>div>
????)
??}
}
Function組件
隨著React Hooks發(fā)布,開(kāi)發(fā)的主流也漸漸的轉(zhuǎn)入了函數(shù)組件,不過(guò)Class組件在舊項(xiàng)目中還是會(huì)用的。所以都學(xué)習(xí)一下。對(duì)比Class組件,函數(shù)組件就非常的簡(jiǎn)單了。在函數(shù)內(nèi)部返回一個(gè)render模板就OK了。如下:
import?React?from?'react'function?FunctionDemo?()?{
??return?(
????<div>
??????我是函數(shù)組件div>
??)
}
export?default?FunctionDemo
Class組件State狀態(tài)
這里著重的開(kāi)個(gè)單章,主要是Class組件中的State值更改,因?yàn)楹瘮?shù)組件最好使用的是hooks,所以單拎出來(lái)主要解一下Class組件下State狀態(tài)。在React不建議直接修改State的值,而是使用setState的方式更新?tīng)顟B(tài)。
this.setState({??default:?'修改后的文件'
})
同樣的,setState后當(dāng)前的值并不會(huì)直接改變。它是一個(gè)異步函數(shù),在異步函數(shù)中可以拿到最新的狀態(tài)。
如果需要進(jìn)行計(jì)算值的累加,推薦使用的是通過(guò)函數(shù)的返回值形式。
“這里的原理類似Vue的組件data的函數(shù)return方式。如果使用對(duì)象方式的話,在多個(gè)setState使用的話會(huì)被后面的任務(wù)覆蓋,從而直接執(zhí)行一次
- - QAQ//?nothis.setState({?index:?this.state.index?+?1?});
this.setState({?index:?this.state.index?+?1?});
//?yes
this.setState({?index:?this.state.index?+?1?});
????this.setState({?index:?this.state.index?+?1?});
this.setState((prevState,?props)?=>?{
??return?{quantity:?prevState.quantity?+?1};
});
組件通信
組件通信是開(kāi)發(fā)中經(jīng)常用到的功能,可謂是靈魂之一了。那么React的組件通信是如何完成的呢?
子組件獲取父組件的值 Props
通過(guò)Props可以使子組件非常快捷的拿到父組件的傳遞過(guò)去的內(nèi)容。
- 1.在子組件上添加屬性名稱和數(shù)據(jù)
- 2.在Class中使用Props
??super(props)
??this.state?=?{
????defaultText:?'我是默認(rèn)的文字'
??}
}
- 3.使用
通過(guò)this.props.父組件綁定的屬性名稱
{?this.props.name?}</p>
定義默認(rèn)的Props屬性
在Vue中可以定義Props的默認(rèn)值,哪怕用戶沒(méi)有傳遞,就會(huì)顯示默認(rèn)Props中定義的內(nèi)容。
ClassDemo.defaultProps?=?{??name:?'我是默認(rèn)的名稱'
??//?...?參數(shù)列表
}
子組件傳遞父組件
通過(guò)Props傳遞一個(gè)函數(shù),當(dāng)子組件需要改變父組件的值時(shí),通過(guò)this.props.[函數(shù)]執(zhí)行回調(diào)。
//?父組件class?App?extends?React.Component?{
??constructor?(props)?{
????super(props)
????this.state?=?{
??????childMessage:?'2222222222222222'
????}
??}
??onPropChange?(newVal)?{
????this.setState({
??????childMessage:?newVal
????})
??}
??render?()?{
????return?(
??????<div?className="App"><p>{?this.state.childMessage?}p><ClassDemo?onPropChange={?this.onPropChange.bind(this)?}>ClassDemo>
????????{/*?<FunctionDemo>FunctionDemo>?*/}div>
????)
??}
}
import?React?from?'react';
class?ClassDemo?extends?React.Component?{
??constructor?(props)?{
????super(props)
????this.state?=?{
??????defaultText:?'我是默認(rèn)的文字'
????}
??}
??changeText?()?{
????this.props.onPropChange('111111111111111')
??}
??render?()?{
????return?(
??????<div?className="App"><button?onClick={?this.changeText.bind(this)?}>更改文本button>div>
????)
??}
}
export?default?ClassDemo;
圖
生命周期
看了官方的生命周期介紹,挺簡(jiǎn)潔的。分別是組件模板選然后,已經(jīng)準(zhǔn)備就緒的時(shí)候,可以做組件加載后的一些邏輯操作,鎮(zhèn)樓神圖。
鎮(zhèn)樓神圖掛載
constructor
構(gòu)造函數(shù)初始化,最先被執(zhí)行,初始化State等等。
getDerivedStateFromProps
這是一個(gè)靜態(tài)方法,需要在前面增加static的屬性
render
渲染函數(shù),返回渲染的內(nèi)容,當(dāng)頁(yè)面產(chǎn)生更新也會(huì)觸發(fā)該方法。
componentDidMount
組件掛載之后,這個(gè)時(shí)候組件已經(jīng)掛載完畢了
更新
getDerivedStateFromProps
組件即將被更新,這里參數(shù)分別對(duì)應(yīng)前后被修改的內(nèi)容,通過(guò)返回一個(gè)布爾值告知是否需要更新視圖。
render
當(dāng)視圖更新,那么Render也會(huì)重新更新
getSnapshotBeforeUpdate
getSnapshotBeforeUpdate在render之后componentDidUpdate之前輸出,類似于中間件用來(lái)做一些捕獲操作。
componentDidUpdate
getSnapshotBeforeUpdate,有三個(gè)參數(shù)prevProps,prevState,snapshot,表示之前的props,之前的state,和snapshot。snapshot是getSnapshotBeforeUpdate返回的值
constructor?(props)?{??super(props)
??this.state?=?{}
??console.log('1.constructor構(gòu)造函數(shù)')
}
componentDidMount?()?{
??console.log('componentDidMount')
??Store.subscribe(()?=>?{
????this.setState({})
??})
}
static?getDerivedStateFromProps?(nextProps,?prevState)?{
??console.log('getDerivedStateFromProps')
??console.log(nextProps,?prevState)
??return?true
}
getSnapshotBeforeUpdate?(prevProps,?prevState)?{
??console.log(prevProps,?prevState)
??return?'top:?200'
}
componentDidUpdate?(prevProps,?prevState,?snapshot)?{
??console.log(prevProps,?prevState,?snapshot)
}
componentWillUnmount?()?{
??console.log('componentWillUnmount')
}
changeText?()?{
??Store.dispatch({
????type:?'changeName',
????value:?'我是ClassDemo中修改的名字:wangly'
??})
}
render?()?{
??console.log('3.render函數(shù)')
??return?(
????<div?className="App"><p>{?Store.getState().redux_name?}p>
??????{?this.state.redux_name?}<button?onClick={?this.changeText.bind(this)?}>更改文本button>div>
??)
}
卸載
componentWillUnmount
組件卸載,我們可以清除一些定時(shí)器,取消網(wǎng)絡(luò)請(qǐng)求。
組件插槽
插槽對(duì)于Vue來(lái)說(shuō)并不是很陌生,在React中插入的節(jié)點(diǎn)會(huì)以Props的方式傳遞。可以通過(guò)pro1ps.children找到并且渲染出來(lái)。
//?父親組件this.onPropChange.bind(this)}><h1>插入的元素?h1>ClassDemo>//?子組件<div?className="App">
??{this.props.children}<button?onClick={this.changeText.bind(this)}>更改文本button>div>
Router路由
路由對(duì)于SPA應(yīng)用來(lái)講可謂是重中之重,沒(méi)有它的話,那么這個(gè)頁(yè)面也就不能成為應(yīng)用,只能稱之為頁(yè)面。兩者可謂天差地別。
安裝react-router-dom --save
#?shellnpm?install?react-router-dom?--save
創(chuàng)建路由模式
在Vue中都知道路由的mode有兩種,一種是hash一種是history模式。分別如下,通過(guò)引入不同的包來(lái)創(chuàng)建不同的Router。
//?histoty
import?{?BrowserRouter?as?Router,?Link,?Route?}?from?'react-router-dom';
//?hash
import?{?Link,?Route,?HashRouter?as?Router?}?from?'react-router-dom';
創(chuàng)建一個(gè)簡(jiǎn)單的路由
通過(guò)as出來(lái)的Router包裹路由快,通過(guò)Link作為跳轉(zhuǎn)的行為容器。這樣一個(gè)基本的路由容器就完成。
“需要通過(guò)使Route進(jìn)行對(duì)組件的聲明配置,才能被Link找到哦。
- - QAQimport?React?from?'react';//?histoty
import?{?BrowserRouter?as?Router,?Link,?Route?}?from?'react-router-dom';
//?hash
//?import?{?Link,?Route,?HashRouter?as?Router?}?from?'react-router-dom';
function?Page1?()?{
??return?(
????<h1>我是Page1h1>
??)
}
function?Page2?()?{
??return?(
????<h1>我是Page2h1>
??)
}
function?Page3?()?{
??return?(
????<h1>我是Page3h1>
??)
}
class?App?extends?React.Component?{
??constructor?(props)?{
????super(props)
????this.state?=?{
????}
??}
??render?()?{
????return?(
??????<div?className="App"><Router><ul><li><Link?to="page1">Page1Link>li><li><Link?to="page2">Page2Link>li><li><Link?to="page3">Page3Link>li>ul><Route?exact?path="/page1"?component={?Page1?}>Route><Route?exact?path="/page2"?component={?Page2?}>Route><Route?exact?path="/page3"?component={?Page3?}>Route>Router>div>
????)
??}
}
export?default?App;
路由傳值
路由傳遞參數(shù)一般使用param和query參數(shù)。通過(guò)給to傳遞一個(gè)對(duì)象的方式來(lái)進(jìn)行數(shù)據(jù)的傳遞。可以看到,向page1的路由上添加了一個(gè):id表示需要傳遞param的id的值,同時(shí)聲明了search的文本和state對(duì)象多種方式傳遞了參數(shù)。以便根據(jù)不同的場(chǎng)景使用。
;<div?className="App"><Router><ul><li><Linkto={{pathname:?'/page1/10',search:?'?roles=[10,?20]',state:?{?name:?'wangly19'?},??????????}}
????????>
??????????Page1Link>li><li><Link?to="page2">Page2Link>li><li><Link?to="page3">Page3Link>li>ul><Route?exact?path="/page1/:id"?component={Page1}>Route><Route?exact?path="/page2"?component={Page2}>Route><Route?exact?path="/page3"?component={Page3}>Route>Router>div>
手動(dòng)跳轉(zhuǎn)
當(dāng)你使用History路由的時(shí)候,某些時(shí)候需要主動(dòng)的跳轉(zhuǎn)道某個(gè)路由,這個(gè)時(shí)候又不能去觸發(fā)節(jié)點(diǎn)行為,所以這個(gè)時(shí)候就可以通過(guò)API的方式,進(jìn)行跳轉(zhuǎn)。使用方式和Vue大差不差。
//?跳轉(zhuǎn)頁(yè)面this.props.history.push(參數(shù)和to的內(nèi)容像素)
this.props.history.push('page1')
//?重定向頁(yè)面
this.props.history.replace('page2')
當(dāng)然還有hash的go方法。
Redux狀態(tài)管理
Redux是類似于Vuex的一個(gè)全局狀態(tài)解決方案,它的功能主要是用來(lái)存儲(chǔ)公有全局狀態(tài)。來(lái)方便管理一些共有配置參數(shù),解決業(yè)務(wù)體積大,結(jié)構(gòu)復(fù)雜的項(xiàng)目提供好的狀態(tài)管理。
“如果項(xiàng)目不是特別需要,盡量不去使用它。
- - QAQ安裝Redux
#?shellnpm?install?redux?--save
創(chuàng)建Store State
看到官方的Demo,是非常容易懂的。下面是官方的代碼,一眼就能看出流程。
import?{?createStore?}?from?'redux'/**
?*?This?is?a?reducer,?a?pure?function?with?(state,?action)?=>?state?signature.
?*?It?describes?how?an?action?transforms?the?state?into?the?next?state.
?*
?*?The?shape?of?the?state?is?up?to?you:?it?can?be?a?primitive,?an?array,?an?object,
?*?or?even?an?Immutable.js?data?structure.?The?only?important?part?is?that?you?should
?*?not?mutate?the?state?object,?but?return?a?new?object?if?the?state?changes.
?*
?*?In?this?example,?we?use?a?`switch`?statement?and?strings,?but?you?can?use?a?helper?that
?*?follows?a?different?convention?(such?as?function?maps)?if?it?makes?sense?for?your
?*?project.
?*/
function?counter(state?=?0,?action)?{
??switch?(action.type)?{
????case?'INCREMENT':
??????return?state?+?1
????case?'DECREMENT':
??????return?state?-?1
????default:
??????return?state
??}
}
//?Create?a?Redux?store?holding?the?state?of?your?app.
//?Its?API?is?{?subscribe,?dispatch,?getState?}.
let?store?=?createStore(counter)
//?You?can?use?subscribe()?to?update?the?UI?in?response?to?state?changes.
//?Normally?you'd?use?a?view?binding?library?(e.g.?React?Redux)?rather?than?subscribe()?directly.
//?However?it?can?also?be?handy?to?persist?the?current?state?in?the?localStorage.
store.subscribe(()?=>?console.log(store.getState()))
//?The?only?way?to?mutate?the?internal?state?is?to?dispatch?an?action.
//?The?actions?can?be?serialized,?logged?or?stored?and?later?replayed.
store.dispatch({?type:?'INCREMENT'?})
//?1
store.dispatch({?type:?'INCREMENT'?})
//?2
store.dispatch({?type:?'DECREMENT'?})
//?1
- 創(chuàng)建Stoge
const?modeStore?=?{
??redux_name:?'我是Redux中聲明的名稱:wangly19'
}
//?聲明Reducer
const?reducer?=?(state?=?modeStore,?action)?=>?{
??return?state
}
//?createStore
import?{?createStore?}?from?'redux';
import?reducer?from?'./reducer'
const?store?=?createStore(reducer)
export?default?store
- 視圖渲染
{?Store.getState().redux_name?}
- 觸發(fā)更新行為dispatch
//?dispatch
changeText?()?{
??Store.dispatch({
????type:?'changeName',
??? value:?'我是ClassDemo中修改的名字:wangly'
??})
}
前提是,需要對(duì)action的方法做一個(gè)聲明。類似于Vuex的Action。
const?reducer?=?(state?=?modeStore,?action)?=>?{??switch?(action.type)?{
????case?'changeName':
??????const?newState?=?{...state}
??????console.log(state)
??????newState.redux_name?=?action.value
??????console.log(newState)
??????console.log(state)
??????return?newState
??
????default:
??????return?state;
??}
}
- 監(jiān)聽(tīng)變化。
作為行為觸發(fā)行為后更新視圖的憑證。在組件注銷時(shí),注意銷毀它哦。
- - QAQcomponentDidMount?()?{??/**
???*?回調(diào)函數(shù)
???*/
??Store.subscribe(()?=>?{
????console.log(Store.getState().redux_name)
????this.setState({})
??})
}
Hooks
“Hooks我準(zhǔn)備寫(xiě)新的文章。
- - QAQ總結(jié)
學(xué)習(xí)React很多都是以Vue的思路先入個(gè)門,不至于一問(wèn)三不知。也明白了知其一而知其三。如果有基礎(chǔ)那么學(xué)習(xí)起來(lái)其實(shí)并不是很困難。但是它的文檔并不如Vue的全面,且對(duì)于某些方面來(lái)說(shuō)。花了一天時(shí)間整理一些基本的學(xué)習(xí)東西
“如果覺(jué)得對(duì)你有幫助,不妨點(diǎn)個(gè)贊哦。
- - QAQ參考資料
React文檔
react生命周期個(gè)人理解
react模板
React路由
Redux
總結(jié)
以上是生活随笔為你收集整理的react项目中的参数解构_一天入门React学习心得的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: qpython获取手机gps_基于Pyt
- 下一篇: 台式电脑如何设置开机密码_设置苹果Mac