前端大陸乃是技術界近年來新興起的板塊,隨著人們對網站互動和效能越來越高, 前往前端大陸修煉 Javascript 的召喚師如過江之鯽,數不勝數,前端奇人異士之多,故修煉之法林林總總,俱不相同, Web 前端的未來尚無定論,內部卻已起了門戶之見, 幸而前端圈核心門派正道大昌,人氣鼎盛,其中尤以 React、Vue、Angular 為三大支柱,是為領袖,今天的故事,便是從 React 峽谷開始的
React 峽谷的每個前端召喚師,根據對 React 技術棧 和前端的理解,分別是青銅,白銀,黃金,鉑金,鑽石,星耀和王者段位,也對應這這個系列教程的七個模組
- 倔強青銅
- 初入峽谷的初始段位,預設召喚師已經有了
ES6
,nodejs
的基礎 - 使用
create-react-app
建立React
開發環境 - 學習
React
世界裡的基本玩法,例如元件化,JSX
,事件監聽,內部state
,元件的props
、生命週期函式等 - 這篇文章主要介紹
React
青銅升白銀需要的基礎知識,看完你就白銀啦
- 初入峽谷的初始段位,預設召喚師已經有了
- 秩序白銀
- 到了白銀段位,基本都是有了基本的操作,不會出現呆萌的站在地方塔下被打死的情況了
- 我們需要買一個皮膚來提升頁面美觀並且多加練習
- 學習使用螞蟻金服
ant-design
的使用
榮耀黃金
- 到了這個階段,召喚師對
React
有了基本的認識,想進一步的提升段位,我們需要提高自己的大局觀 - 學習使用
React-Router4
來讓我們有多面作戰能力 - 學會使用
BrowserRouter
,Router
,Link
等元件 - 學會使用
Redux
和隊友配合,修煉大局觀 - 瞭解單項資料流開發模式和
Redux
的各種概念,如dispatch
,action
,reducers
- 使用
react-redux
更好的和Redux
配合有大局觀意識,上鉑金也是很 easy 了
- 到了這個階段,召喚師對
尊貴鉑金
- 很多召喚師卡在鉑金上不去,因為鉑金想上鑽石,需要了解更多的細節和原理
React
原理剖析- 對自己技能的原理有深刻的瞭解,上鑽石必備
永恆鑽石
- 鑽石段位開始了徵兆模式,召喚師的技能池要足夠深才能更進一步,對自己擅長技能的理解也要更深刻
Redux
中介軟體機制,實現自己的中介軟體- 常見的React 效能優化方式
- 服務端渲染
Redux
之外其他的資料解決方案如mobx
,dva
至尊星耀
- 這個段位已經是獨當一面的強者了,目標僅限於 React 這個庫很難更近一層,需要了解更底層的原理
Redux
原理剖析+實現自己的Redux
React-Router
+實現自己的React-Router
Webppack
工作機制和原理剖析Babel
工作機制和原理剖析
- 最強王者
- 達到最強王者已經是頂尖召喚師,在整個 React 峽谷都是鼎鼎大名的存在,聽說上面還有傳說中的榮耀王者的段位,我這輩子是達不到了,也沒法教你們了,囧
- 這個階段,我只推薦《程式設計師健康指南》一本書,保持身心健康,成為榮耀王者是早晚的事
開始之前,做個小廣告,歡迎大家關注我在慕課網的React實戰課程Redux+React Router+Node.js全棧開發
下面開始我們的正文,倔強青銅篇目錄
- 環境搭建
- 第一個元件
- 元件巢狀和屬性傳遞
- 狀態處理
- 生命週期
環境搭建
預設大家已經有 node 環境了,先安裝腳手架
npm install create-react-app -g複製程式碼
然後建立專案,並啟動
create-react-app bronze
cd bronze
npm start複製程式碼
看到下面的圖,意味著第一個 React
應用已經啟動起來了
我們開啟 src 目錄
src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
└── registerServiceWorker.js複製程式碼
index.js
是入口檔案,核心內容就是分別引入 React
和 ReactDom
,然後渲染了一個元件 App
在#root
這個元素上
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />,document.getElementById('root'));複製程式碼
然後重點看下 App.js
是我們元件的具體內容
import React, { Component } from 'react'
class App extends Component {
render() {
return (
<div className="App">
<p>
To get started, edit <code>src/App.js</code> and save to reload.
</p>
</div>
);
}
}
export default App;複製程式碼
這個基本上是最簡單的 React
元件了,自己實現元件也是分這麼幾個步驟
import React
- 新建一個類,繼承
React.Component
,React
裡每個元件都可以寫成一個類 - 類的
render
函式返回值,就是顯示在頁面的內容 render
裡返回的是東西有點詭異,表面上是html
其實Babel
會把JSX
轉成React.createElememt
來執行- 由於
JSX
本質就是 js,class
是 js 的關鍵字,所以要用className
代替 - 如果想在
JSX
裡渲染變數,使用{}
包裹即可
現在Babel官網],看下 JSX
編譯後的程式碼,再劃下重點,所謂的 JSX
,其實就是js 物件,再用 ReactDom.render
方法,渲染成dom
// jsx
<div className="App">
<p>hello react</p>
</div>
// 轉換後
React.createElement(
"div",
{ className: "App" },
React.createElement(
"p",
null,
"hello react"
)
)複製程式碼
第一個元件
我們實現自己的第一個元件,修改 App.js
為
import React, { Component } from 'react'
class App extends Component {
render() {
const level='最強王者'
return (
<div>
<h2>我們的目標是{level}</h2>
</div>
)
}
}
export default App複製程式碼
由於JSX
本質上其實就是 js,所以我們可以在{}
裡面使用 js 的表示式等功能,比如三元、函式、變數等等,還可以把陣列對映為列表,我們把程式碼修改為
import React, { Component } from 'react'
class App extends Component {
render() {
const level='最強王者'
const isKing = true
const title = isKing
? <p>早睡早起,理性遊戲</p>
: <h2>我們的目標是{level}</h2>
const wordList = ['俺老孫來也','有妖氣','取經之路,就在腳下']
return (
<div>
{title}
{isKing ? <p>我就是王者</p>: null}
<ul>
{wordList.map(v=><li key={v}>{v}</li>)}
</ul>
</div>
)
}
}
export default App複製程式碼
這裡要稍微注意一點,就是 render
裡,如果 return
多個元素,必須有一個父元素包裹,否則會有個報錯
我們在return 之外把 JSX
複製給變數,JSX
裡也可以在{}
內部使用三元表示式,大家可以修改 isKing
是 false
試一試
然後就是渲染列表,我們使用 map
函式直接對映為 JSX
的陣列,記得列表裡每個元素都有一個 key
屬性,關於它的作用,我們講虛擬dom 的時候會介紹
元件巢狀和屬性傳遞
如果我們繼續設計我們的應用,現在再設計一個Tank
元件,可以直接放在 App
裡使用,並且可以傳遞一個屬性,在元件內部,使用 this.props.key
獲取
import React, { Component } from 'react'
class App extends Component {
render() {
const level='最強王者'
const isKing = true
const title = isKing
? <p>早睡早起,理性遊戲</p>
: <h2>我們的目標是{level}</h2>
return (
<div>
{title}
{isKing ? <p>我就是王者</p>: null}
<Tank name='程咬金'></Tank>
</div>
)
}
}
class Tank extends Component {
render() {
return (
<div>
<h3>{this.props.name}是一個坦克</h3>
</div>
)
}
}
export default App複製程式碼
如果我們的元件只有一個 render
方法,還可以寫成一個函式,props 是函式的引數,我們稱呼這種元件為無狀態元件,這種元件的特點,就是返回只和 props 有關,複用性高
function Tank(props){
return (
<div>
<h3>{props.name}是一個坦克</h3>
</div>
)
}複製程式碼
這樣我們就可以把應用分成多個元件,然後用拼積木的形式拼接應用,但是現在的元件都沒法變化,下一步,我們學習 React 的狀態管理,也就是 state
React 狀態管理和事件監聽
我們通過在建構函式constructor裡初始 state,其實就是一個普通的 js 物件,然後可以呼叫 this.setState函式修改 state,每次 setState,都會重新渲染元件
元件裡可以使用 onClick來繫結一個函式,可以監聽使用者的事件,話不多說看程式碼
class App extends Component {
constructor(props){
super(props)
this.state = {
isKing:true
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(){
this.setState({
isKing: !this.state.isKing
})
}
render() {
const level='最強王者'
const title = this.state.isKing
? <p>早睡早起,理性遊戲</p>
: <h2>我們的目標是{level}</h2>
return (
<div>
<button onClick={this.handleClick}>點我</button>
{title}
{this.state.isKing ? <p>我就是王者</p>: null}
<Tank name='程咬金'></Tank>
</div>
)
}
}複製程式碼
我們需要關注的點,一個是constructor
,我們稱之為建構函式,元件初始化狀態放在這裡,設定了 isKing
是 true
,然後button
元素上的 onClick
的時候,執行handleClick
,在handleClick
內部,呼叫 this.setState
來修改 isKing
constructor
函式裡的 bind
是強行把handleClick
的 this
繫結在元件上,否則 onClick
的時候會獲取 this
引用出錯,解決這個問題還有其他的形式,可以不用寫 bind
這一行
import React, { Component } from 'react'
class App extends Component {
constructor(props){
super(props)
this.state = {
isKing:true
}
this.handleClick = this.handleClick.bind(this)
}
// 在constructor裡手動 bind
handleClick(){
this.setState({
isKing: !this.state.isKing
})
}
// 繫結的時候傳遞箭頭函式
handleClick1(){
this.handleClick()
}
// 定義的時候是剪頭函式
handleClick2 = ()=>{
this.handleClick()
}
// onClick 的時候直接繫結
handleClick3(){
this.handleClick()
}
render() {
const level='最強王者'
const title = this.state.isKing
? <p>早睡早起,理性遊戲</p>
: <h2>我們的目標是{level}</h2>
return (
<div>
<button onClick={this.handleClick}>點我</button>
<button onClick={()=>this.handleClick1()}>點我1</button>
<button onClick={this.handleClick2}>點我2</button>
<button onClick={this.handleClick3.bind(this)}>點我3</button>
{title}
{this.state.isKing ? <p>我就是王者</p>: null}
<Tank name='程咬金'></Tank>
</div>
)
}
}複製程式碼
生命週期
最後要介紹的,就是 React
元件的生命週期,每個元件在不同的時期,會有不同的鉤子函式執行,比如元件載入完畢後,會執行 componentDidMount
鉤子函式
class App extends Component{
componentDidMount(){
console.log('元件渲染完畢')
}
render(){
console.log('元件正在渲染')
return <h2>倔強青銅</h2>
}
}
// 元件正在渲染
// 元件渲染完畢複製程式碼
React
在不同的階段,會執行不同的函式,我從網上找了個圖,很清晰的說明各個生命週期函式執行的時機,
class App extends Component {
constructor(props){
super(props)
this.state = {
isKing:true
}
this.handleClick = this.handleClick.bind(this)
console.log('constructor App 的建構函式,初始化先執行')
}
handleClick(){
this.setState({
isKing: !this.state.isKing
})
}
componentWillMount(){
console.log('componentWillMount,元件 App 準備渲染')
}
componentDidMount(){
console.log('componentDidMount,元件 App 渲染完畢')
}
shouldComponentUpdate(){
console.log('shouldComponentUpdate,判斷 App 元件是否應該渲染, 預設返回 true')
return true
}
componentWillUpdate(){
console.log('componentWillUpdate,元件 App 準備更新了')
}
componentDidUpdate(){
console.log('componentDidUpdate, 元件 App 更新完畢了')
}
render() {
const level='最強王者'
const title = this.state.isKing
? <p>早睡早起,理性遊戲</p>
: <h2>我們的目標是{level}</h2>
const wordList = ['俺老孫來也','有妖氣','取經之路,就在腳下']
console.log('元件 App 正在渲染')
return (
<div>
<button onClick={this.handleClick}>點我</button>
{title}
{this.state.isKing ? <p>我就是王者</p>: null}
<ul>
{wordList.map(v=><li key={v}>{v}</li>)}
</ul>
<Tank name='程咬金'></Tank>
</div>
)
}
}
// 首次載入列印
constructor App 的建構函式,初始化先執行
componentWillMount,元件 App 準備渲染
元件 App 正在渲染
componentDidMount,元件 App 渲染完畢
// 點選按鈕修改狀態時列印
shouldComponentUpdate,判斷 App 元件是否應該渲染, 預設返回 true
componentWillUpdate,元件 App 準備更新了
元件 App 正在渲染
componentDidUpdate, 元件 App 更新完畢了複製程式碼
除了上面介紹的,還有需要注意的
React16
新增的componentDidCatch
生命週期,用來處理報錯shouldComponentUpdate
返回false
,那麼元件就不會渲染- 如果是子元件,還有個
componentWillReceiveProps
- 元件解除安裝有
componentWillUnmount
,用來做資源的清理 - 合理利用生命週期,在不同的階段做不同的事情
如果你能看到這裡,那真的對React
是真愛,恭喜你,你已經是秩序白銀啦,領取徽章
歡迎大家關注我在慕課網的實戰課程Redux+React Router+Node.js全棧開發
下期預告:秩序白銀篇-- 使用 ant-design UI庫,有問題留言,我們還可以開黑,一起上王者