手挽手帶你學React入門第一期,帶你熟悉React的語法規則,消除對JSX的恐懼感,因爲如今開發中都是使用ES6語法開發React,因此此次也使用ES6的模式進行教學,若是你們對ES6不熟悉的話,先去看看class相關內容吧,這裏我也慢慢帶你們一步一步學會React。javascript
視頻教程可移步個人我的博客:http://www.henrongyi.tophtml
React是Facebook的一羣變態們開發的一個特別牛X的框架。它其實是一個虛擬DOM,而後在這個DOM中,要用什麼組件就能飛速加載進來,不要的時候,立刻給刪咯(實際上就是個前端框架,都是這麼個意思,VUE,NG都是,只不過他們的數據流向不一樣而已,React區別就在於,單向數據流。),React 扮演着 MVC 結構中 V 的角色,後面我會用到基於FLUX架構的Redux讓咱們的整個項目變成MVC架構。總之,React也是hie牛X的。前端
React是一款很是牛X的前端框架,它的衍生物React-Native可讓你開發接近原生體驗的NativeApp,它適合的範圍至關普遍,前端,後端,手機端,都有很好的兼容性。總而言之,hie牛X。vue
如今的開發中React項目實際上都是使用ES6語法來編寫,而且,咱們如今有不少成熟的腳手架可使用(create-react-app,dva等),不過國際慣例,咱們要從最基礎的用法開始編寫。咱們採用ES6寫法來進行教學,同時使用webpack工具,這裏會用到不少相關配置,你們能夠在這個過程當中體驗ES6的精妙。java
配置基礎webpack環境react
這裏你們能夠不去深刻理解,先跟着我一步一步配置出來webpack
開始以前,你們能夠去官網:https://reactjs.org/ 下載最新的React(當前版本v16.7.0) 中文地址:https://react.docschina.org/ git
因爲咱們不使用腳手架,因此咱們須要先建立咱們本身的webpack包,第一步es6
mkdir helloReact cd helloReact
首先你們命令行輸入github
webpack v
若是正常出現版本號 而且是 3.6.0版本,那麼咱們就能夠按照教程繼續走下去了
若是沒有的話 那麼咱們就須要命令行繼續
cnpm i webpack@3.6.0 -S -g
到這裏應該能夠正常使用webpack了
接下來 咱們命令行輸入
npm init -y // 這其實是 初始化一個項目 而且所有默認 固然若是你想看看裏面有啥的話 就把-y拿掉就行了 npm i //這裏是把webpack依賴安裝到本包內部 npm i webpack-dev-server@2.11.1 --save-dev //安裝本地運行服務器 npm i webpack-cli --save-dev //依賴腳手架
運行完成之後,咱們會獲得一個package.json文件 打開看看
{ "dependencies": { "webpack": "^3.6.0" //依賴包和版本 }, "name": "helloreact", //項目名 "version": "1.0.0", // 版本號 "main": "index.js", //入口文件 "scripts": { //npm run 加這裏面的key就能夠快速執行命令行 "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", // 做者 "license": "ISC", "description": "" //簡介 }
這裏面其實是咱們項目的一些基礎信息
咱們須要本身配置webpack和babel 這裏咱們須要建立兩個文件
這裏面咱們要設置入口文件,輸出文件,babel,webpackServer等等,這裏不作太詳細的介紹 你們能夠直接複製代碼,後面可能會開專門的webpack視頻課程。
小小的介紹一下這些都是幹什麼用的
babel-core 調用Babel的API進行轉碼 babel-loader babel-preset-es2015 用於解析 ES6 babel-preset-react 用於解析 JSX babel-preset-stage-0 用於解析 ES7 提案
命令行輸入
npm install --save-dev babel-core babel-loader@7.1.5 babel-preset-es2015 babel-preset-react babel-preset-stage-0
接下來咱們在helloReact 文件夾中建立 webpack.config.js 文件
// webpack.config.js 直接複製便可 const path = require("path"); module.exports = { /*入口*/ entry: path.join(__dirname, 'src/index.js'), /*輸出到dist文件夾,輸出文件名字爲bundle.js*/ output: { path: path.join(__dirname, './dist'), filename: 'bundle.js' }, /*src文件夾下面的以.js結尾的文件,要使用babel解析*/ /*cacheDirectory是用來緩存編譯結果,下次編譯加速*/ module: { rules: [{ test: /\.js$/, use: ['babel-loader?cacheDirectory=true'], include: path.join(__dirname, 'src') }] }, plugins : [], devServer : { disableHostCheck: true, inline: true, port:9527, contentBase: path.join(__dirname, "/"), } }
接下來咱們在helloReact 文件夾中建立 .babelrc 文件
{ "presets": [ "es2015", "react", "stage-0" ], "plugins": [] }
而後咱們在package.json文件的script中添加
//package.json { "dependencies": { "webpack": "^3.6.0" }, "name": "helloreact", "version": "1.0.0", "main": "index.js", "scripts": { "server": "webpack-dev-server", "build": "webpack", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "description": "", "devDependencies": { "babel-core": "^6.26.3", "babel-loader": "^7.1.5", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "babel-preset-stage-0": "^6.24.1", "webpack-cli": "^3.1.2", "webpack-dev-server": "^2.11.1" } }
這些配置完了,咱們就在helloReact mkdir src 而且在src中建立 index.js文件
在 根路徑 helloReact下建立 index.html
由於這裏咱們要用到 react了 因此須要命令行安裝一下 react
cnpm install --save react react-dom
html文件以下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <div id="app"></div> </body> <script src="bundle.js"></script> </html>
js 文件以下
import React from 'react'; //es6 引入react import ReactDom from 'react-dom'; //es6 引入reactReacrDom ReactDom.render( //ReactDom渲染<div>hello React</div> 這個html標籤 到 id='app'這個標籤下 <div>Hello React!</div>, document.getElementById('app'));
一切都寫完了 咱們運行服務 npm run server 來看一眼
若是你看到屏幕顯示出 Hello React! 那麼恭喜你 環境配置完了 我們能夠開始學習 React 了
若是你配置了半天還沒配置成功
到個人github下載代碼吧。。。https://github.com/piexlmax/h...
React的Hello World
咱們看到上面的代碼
import React from 'react'; //es6 引入react import ReactDom from 'react-dom'; //es6 引入reactReacrDom ReactDom.render( //ReactDom渲染<div>hello React</div> 這個html標籤 到 id='app'這個標籤下 <div>Hello React!</div>, document.getElementById('app'));
這是一個簡單的渲染 是否是根本看不到 React的組件化模式呢?
因此這裏 咱們須要寫一個根部組件,之後的組件都放跟組件裏面,這個JS就理所固然成了一個入口文件了
這裏 咱們在 src下面建立一個app.js文件
app.js
import React, {Component} from 'react'; // 這裏咱們引入 react 和 react的Component // 建立 Hello 這個class(class屬於ES6內容) 而後繼承 Component 咱們就成功地建立了一個 react組件 export default class App extends Component { render() { return ( <div> Hello,World! </div> ) } }
index.js 咱們須要改寫爲這樣
import React from 'react'; import ReactDom from 'react-dom'; import App from './app.js' //引入咱們的根組件App ReactDom.render( //把App 渲染到 id=app的dom中 <App/>, document.getElementById('app'));
到這裏 咱們已經實現了一個真正意義上的Hello World了!
開始玩React了,那就必需要用到jsx語法,什麼是jsx呢?
JSX是一種JavaScript的語法擴展。JSX與模板語言類似,但它具備JavaScript的所有功能。JSX會被編譯爲React.createElement()方法調用,將返回名爲「React elements」的普通JavaScript對象。
上面代碼裏咱們看到 咱們的html其實是在js中的render函數中書寫的,是一個React擴展,容許咱們編寫看起來像 HTML的JavaScript 。
切記 自定義組件必定要大寫字母開頭 return加括號 而且左括號要和return在同一行 只能return一個標籤,其他內容都要在這個標籤內部
export default class App extends Component { render() { return ( <div> Hello,World! </div> ) } }
像是這樣一段代碼,實際上咱們真正使用的時候,已經通過了一次編譯,編譯事後它長這樣。
export default class App extends React.Component { render() { return ( React.createElement( 'div', 'Hello,World!' ) ); } }
下面的這一段代碼是否是就不容易理解了?這其實是js能夠幫咱們去書寫dom的代碼。
在React中JSX你能夠理解爲咱們能夠在js中寫HTML代碼了 更通俗一點
export default class App extends Component { // 方法 生命週期 state 等 render() { return ( // HTML模板 ) } }
state
咱們以前學過VUE,VUE中每一個組件的數據存在本身的data中,那麼在React中,數據存在哪裏呢?沒錯狀態state中。
因爲咱們這裏用的是ES6的class 因此 咱們子類constructor中必須先調用super才能引用this。
因此咱們這裏應該這麼寫state
export default class App extends Component { constructor(){ super() this.state={ hello:"hello World" } } render() { return ( <div> {this.state.hello} </div> ) } }
這裏咱們能夠看出,咱們想要在render中使用js 就須要用一個{} 這裏面的內容一樣能夠書寫簡單的js表達式。
rander函數中使用state和JS表達式
export default class App extends Component { constructor(){ super() this.state={ hello:"hello World" } } render() { return ( <div> <ul> <li>展現state中的數據:{this.state.hello}</li> <li>三元,短路等,這裏用三元示例{this.state.hello?"存在hello":"不存在hello"}</li> <li>簡單計算{1+1}</li> <li>JS表達式{Math.floor(Math.random()*10)}</li> </ul> </div> ) } }
方法的聲明以及修改state
聲名方法咱們有兩種模式,一種是直接書寫 方法名(參數){代碼段}模式,這樣的模式在調用的時候須要手動bind(this)
還有一種就是使用es6的箭頭函數,讓其this指向自身
修改state數據須要調用 this.setState()方法 內部接收一個對象 要修改哪一個key 就在對象內部填寫這個key,而且後面的值就是你要修改的內容,若是,key在state中不存在,則會在state中增長這個key
export default class App extends Component { constructor(){ super() this.state={ hello:"hello World" } } bye(){ this.setState({ hello:"bye world" }) } byebye=()=>{ this.setState({ helloo:"bye world" }) } render() { return ( <div> <ul> <li>非箭頭函數:{this.state.hello}</li> <li>箭頭函數:{this.state.helloo}</li> </ul> <button onClick={this.bye.bind(this)}>無箭頭</button> {/* 這裏使用bind來綁定this 若是傳參的話this.bye.bind(this,參數1,參數2) */} <button onClick={()=>{this.byebye()}}>箭頭函數</button> {/* 這裏是箭頭函數的默認屬性來搞定了this問題 若是傳參的話()=>{this.byebye(參數1,參數2)*/}} </div> ) } }
這裏須要注意,只有觸發了state的變化,纔會致使組件的從新渲染
你們在vue中使用v-for 就可以完成循環生成組件這樣的操做了,在react中咱們應該怎麼作呢?
循環語句
咱們說過 jsx 裏面是能夠自由自在地使用js的 通常狀況下咱們使用map循環
在循環的時候,每個return出來的標籤都須要添加 key={鍵值} 「鍵值」是建立元素數組時須要包含的特殊字符串屬性。鍵值能夠幫助React識別哪些元素被更改,添加或刪除。所以你應當給數組中的每個元素賦予一個肯定的標識
export default class App extends Component { constructor(){ super() this.state={ arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}] } } render() { return ( <div> {/* 咱們說過 jsx 裏面是能夠自由自在地使用js的 這裏咱們來玩一個循環生成li */} <ul> {this.state.arr.map((item,key)=>{ return(<li key={key}>{item.text}</li>) })} </ul> </div> ) } }
判斷語句
判斷語句咱們通常使用短路表達式 三元表達式來展現咱們想要展現的內容,可是若是須要複雜的條件判斷,那麼咱們最好是寫一個自執行函數,而後再函數體內你就能夠隨心所欲了,記住必定要return你想要獲得的dom標籤。
export default class App extends Component { constructor(){ super() this.state={ arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}] } } render() { return ( <div> {/*簡單的三元和短路實例*/} {this.state.arr.length==3?<div>我是三元判斷的三個</div>:<div>我是三元判斷的不是三個</div>} {this.state.arr.length==3&&<div>我是短路判斷的三個</div>} {/* 咱們說過 jsx 內部支持簡單的表達式 若是咱們使用 if條件句的話 會致使報錯*/} {/* if(this.state.arr.length==3){ return(<div>有三個</div>) } */} {/* 咱們說過 jsx 這已是js代碼段而不是簡單語句了,咱們簡單判斷可使用三元或者短路表達式來進行,可是複雜一點的,咱們可使用以下方法*/} {(()=>{ if(this.state.arr.length==3){ return(<div>數組有三個元素</div>) }else{ return(<div>數組有不是三個元素</div>) } })()} </div> ) } }
循環判斷嵌套
有些時候咱們須要根據特定條件去循環,而後渲染出篩選事後的數據,這時候就須要循環和判斷嵌套使用了,其實也至關簡單,咱們的循環其實是一個簡單的js表達式,內部的function中能夠隨意書寫js,記得return就行了
export default class App extends Component { constructor(){ super() this.state={ arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}] } } render() { return ( <div> {this.state.arr.map((item,key)=>{ if(key%2==0){ return(<div key={key}>我是能夠餘2的{item.text}</div>) }else{ return(<div key={key}>我是不能餘2的{item.text}</div>) } })} </div> ) } }
有些時候咱們不得不去操做DOM,那這時候 咱們須要用到 ref 屬性
React支持一個能夠附加到任何組件的特殊屬性ref。ref屬性能夠是一個字符串或一個回調函數。當ref屬性是一個回調函數時,函數接收底層DOM元素或類實例(取決於元素的類型)做爲參數。這使你能夠直接訪問DOM元素或組件實例。
另外這裏應該注意 不要過分使用 Refs。
export default class App extends Component { constructor(){ super() this.state={ arr:[{text:"qm"},{text:"奇淼"},{text:"大帥逼"}] } } render() { return ( <div> {this.state.arr.map((item,key)=>{ if(key%2==0){ return(<div ref="link" key={key}>我是能夠餘2的{item.text}</div>) {/* 這樣咱們能夠經過 this.refs.link 獲取到這個dom 而且操做dom了 */} }else{ return(<div key={key}>我是不能餘2的{item.text}</div>) } })} </div> ) } }
到這裏咱們已經學會了React的基本組件內部的操做了,React相對於Vue來講更加靈活,可是惟一的缺點是數據流是單向的,必須經過setState來修改,對於處理表單來講會有些麻煩,不過有些UI框架,插件幫咱們處理了這些大麻煩。寫寫玩玩吧React仍是比較簡單的。