前端大陸乃是技術界近年來新興起的板塊,隨着人們對網站交互和性能愈來愈高, 前往前端大陸修煉 Javascript 的召喚師如過江之鯽,數不勝數,前端奇人異士之多,故修煉之法林林總總,俱不相同, Web 前端的將來尚無定論,內部卻已起了門戶之見, 幸而前端圈核心門派正道大昌,人氣鼎盛,其中尤以 React、Vue、Angular 爲三大支柱,是爲領袖,今天的故事,即是從 React 峽谷開始的css
React 峽谷的每一個前端召喚師,根據對 React 技術棧 和前端的理解,分別是青銅,白銀,黃金,鉑金,鑽石,星耀和王者段位,也對應這這個系列教程的七個模塊html
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 了尊貴鉑金node
React
原理剖析永恆鑽石react
Redux
中間件機制,實現本身的中間件Redux
以外其餘的數據解決方案如 mobx
,dva
至尊星耀程序員
Redux
原理剖析+實現本身的 Redux
React-Router
+實現本身的 React-Router
Webppack
工做機制和原理剖析Babel
工做機制和原理剖析開始以前,作個小廣告,歡迎你們關注我在慕課網的React實戰課程Redux+React Router+Node.js全棧開發npm
下面開始咱們的正文,倔強青銅篇目錄redux
默認你們已經有 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
咱們經過在構造函數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庫,有問題留言,咱們還能夠開黑,一塊兒上王者