官網:https://reactjs.org/javascript
文檔:https://reactjs.org/docs/hello-world.htmlcss
中文:http://react.css88.com/html
2013年被開源,2014年在中國完全火爆。vue
React是CMD架構,現階段須要webpack打包java
npm install -g webpack@4.9.1
必須安裝如下三個依賴:node
npm install --save-dev babel-core babel-loader babel-preset-env
React採用jsx語法,JSX語法是什麼?react
就是全球惟一標準的JavaScript和XHTML結合開發最優雅的語法。webpack
瀏覽器不識別JSX語法,因此須要babel將JSX語法翻譯,babel要裝一個新的presetweb
npm install --save-dev babel-preset-react
安裝完依賴,修改webpack.congif.js文件中的preset配置:npm
const path = require('path'); module.exports = { entry: "./www/app/main", output : { path: path.resolve(__dirname, "www/dist"), filename : "bundle.js", }, watch:true, mode : "development", module: { rules: [ { test: /\.js?$/, include: [path.resolve(__dirname, "www/app")], exclude: [path.resolve(__dirname, "node_modules")], loader : "babel-loader", options: { presets: ["env","react"] }, //要翻譯的語法 } ] } }
還要安裝react和react-dom包:
npm install --save react react-dom
react是核心庫
react-dom提供了與DOM操做的功能庫
注意:項目文件夾名字千萬不要叫react,很坑。
在index.html上放「掛載點」的盒子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Document</title> </head> <body> <div id="app"></div> </body> <script type="text/javascript" src="dist/bundle.js"></script> </html>
app/main.js
import React from "react"; import ReactDOM from "react-dom"; ReactDOM.render( <div> <h1>你好,我是react,來自Facebook公司</h1> </div>, document.getElementById('app') );
運行webpack,直接打開頁面:
React是全部react項目的入口
React-dom負責react Element添加到HTML頁面的掛載點上
react-dom 這個包提供了你的app最高等級的API,提供了元素的掛載和上樹的方法
render() 接收兩個參數,第一個參數是react元素,第二個參數是掛載點,用來讓react元素進行掛載。
Vue在寫實例,而React在寫類(構造函數)。
組件叫「component」,就是HTML、CSS和JS行爲的一個封裝。
Vue中的組件是一個.vue文件(實際上是普通的JSON對象),React中,組件是一個類(構造函數)。
建立App.js文件,這是一個組件,必須按照要求寫標準殼,這個殼咱們叫rcc殼「react class component」,react的類式組件:
import React from "react"; // 默認暴露一個構造函數(類組件) export default class App extends React.Component{ constructor(){ super(); } render(){ return <div> <h1>我是App組件!</h1> </div> } }
注意:
1)這個文件的默認暴露就是一個類,這個類的類名必須和文件名相同。 2)文件名和類名的首字母必須大寫!React中組件的合法名字首字母必須是大寫字母。 3)這個類必須繼承自React.Component類,也就是說,rcc殼必須是extends React.Component的寫法。 4)這個類必須有構造器constructor,構造器裏面必須調用超類的構造器,super(); 5)這個類必須有render函數,render函數中必須return一個jsx對象。並且這個jsx對象必須被惟一的標籤包裹。
在main.js主文件中引入組件,而後用自定義標籤:
import React from "react"; import ReactDOM from "react-dom"; // 引入組件 import App from "./App.js"; ReactDOM.render( <div> <App></App> <h1>你好,我是react,來自Facebook公司</h1> </div>, document.getElementById("app") );
注意:
引入的組件必須路徑以./開頭
組件要使用,就將這個組件的名字(類名、文件名)進行標籤化便可
原理就是這個App類在被實例化。
由於類的名字是大寫字母,因此全部的自定義組件標籤名字必定是大寫字母開頭的
在react中,全部以大寫字母開頭的都是組件,而不是標籤。
ReactDOM.render(根jsx,根的掛載點)
ReactDOM只能出現一次,可是很是厲害,能夠和HTML結合
jsx,如今一概在js文件夾中開發,並非傳統放html開發
HTML、CSS、JS都被構建到bundle.js文件夾中。
安裝如下插件,輸入rcc便可快速生成一個組件的語法:
main.js文件中引入App.js組件,App組件裏面的render函數還能夠引入其餘組件。
components/Child.js
import React from "react"; export default class Child extends React.Component { constructor() { super(); } render() { return <div> <h1>我是Child子組件!</h1> </div> } }
App父組件中引入:
import React from "react"; import Child from "./components/Child"; // 默認暴露一個構造函數(類組件) export default class App extends React.Component { constructor() { super(); } render() { return <div> <h1>我是App組件!</h1> <Child></Child> <Child></Child> <Child></Child> </div> } }
簡單的說:在react中作一個組件:
第一步:建立一個類並暴露
第二步:引入這個類,而後用這個類的類名當作組件的標籤(實例化)
一個函數,若是是大寫字母開頭,而且return一個React Element就是一個組件。
好比App.js組件中,建立一個Child1的函數,這個函數直接返回JSX語法的React Element,此時這個函數就是組件,這個函數直接成爲自定義標籤,就能夠用了。
import React from "react"; import Child from "./components/Child"; // 默認暴露一個構造函數(類組件) //定義一個自定義的函數組件 const Child1 = ()=> <div> <h1>我是Child1函數式組件!</h1> </div> export default class App extends React.Component { constructor() { super(); } render() { return <div> <h1>我是App組件!</h1> <Child></Child> <Child1></Child1> </div> } }
注意:
1)render是一個函數,因此函數裏面固然能夠定義另外一個函數。咱們用const來定義一個箭頭函數,這個箭頭函數的名字,必須首字母大寫。react中全部標籤名字是首字母大寫的,將被斷定爲咱們本身的組件。
2)這個函數裏面return了一個jsx對象,注意,不要加引號。初學者會有不少不適。
3)這個組件也是經過「標籤」的形式來上樹的!
4)函數式組件比類組件差不少功能不少,後面會說。
5)至於何時用什麼組件、圓括號中能不能傳入參數,後面會說。
函數式組件有個缺點,沒有state,沒有生命週期。
全部對React不適應,都是JSX語法形成的,JSX語法淡化了JS和HTML之間的「邊界」。
錯誤的:
import React from "react"; import ReactDOM from "react-dom"; // 引入組件 import App from "./App.js" ReactDOM.render( <App></App> <App></App> <App></App> , document.getElementById('app') );
有多個組件,必須有一個標籤包裹全部組件:
import React from "react"; import ReactDOM from "react-dom"; // 引入組件 import App from "./App.js" ReactDOM.render( <div> <App></App> <App></App> <App></App> </div> , document.getElementById('app') );
好比table不能直接嵌套tr,必需要有tbody
import React from "react"; export default class App extends React.Component { constructor() { super(); } render() { return <div> <table> <tbody> <tr> <td>1</td> <td>2</td> </tr> </tbody> </table> </div> } }
好比這樣也是錯誤的:
<p><div>111</div></p>
return後面直接跟着div,不能換行
若是想換行,必須加圓括號包裹。
import React from "react"; export default class App extends React.Component { constructor() { super(); } render() { return ( <div> <h1>我是App組件</h1> </div> ) } }
由於jsx語法被babel-loader翻譯(babel-perset-react),因此標籤必須嚴格封閉,不然翻譯會報錯。
錯誤的: <br> <hr> 正確的: <br/> <hr/> 錯誤的: <input type="text"> 正確的: <input type="text" />
由於JS中class是關鍵字,因此類名必須用className
錯誤的
<div class="box"></div>
正確的:
<div className="box"></div>
for要用htmlFor代替:
錯誤的: <label for=""></label> 正確的: <label htmlFor=""></label>
能夠在jsx內部,用單個「{}」大括號進行一些js表達式的插入,咱們叫作插值。
{} 只能出如今React element中,簡化了連字符串工做。
import React from "react"; export default class App extends React.Component { constructor() { super(); } render() { const year = 10000; const pingfang = (n)=>{ return n * n } const arr = [1000,2000,3000,4000] return <div> <h1>{5000 * 2}年</h1> <h1>{year}年</h1> <h1>{pingfang(100)}年</h1> <h1>{arr.reduce((a,b)=>a + b)}年</h1> <h1>{parseInt(Math.random() * 100)}年</h1> <h1>{3 > 8 ? 10000 : 1}年</h1> </div> } }
不能出現的語法:
不能定義變量:
<h1>{var a = 100}</h1>
不能定義函數:
<h1>{function name(){}}</h1>
應該在return以前定義:
render() { const pingfang = (n)=> n * n return ( <div> <h1>我愛你{pingfang(100)}年</h1> </div> ) }
不能出現for循環、if語句、while、do語句:
<h1>{for(var i = 0;i < 100;i++){}}</h1>
JSX不能出現對象(JSON)。
render() { const obj = {"a":100,"b":200} return ( <div> <h1>{obj}</h1> </div> ) }
此時會報錯,若是要在頁面顯示JSON,應該:
render() { const obj = {"a":100,"b":200} return ( <div> <h1>{JSON.stringify(obj)}</h1> </div> ) }
JSX表達式不能出現引號中,好比有一個變量
render() { const picUrl = "baby1.jpg" return <div> <img src="images/{picUrl}.jpg" /> </div> }
正確的應該先寫在外層的{}:
render() { const picUrl = "baby1"; const tip = '這是黃曉明老婆'; const url = 'http://www.baidu.com/' return <div> <img src={"images/" + picUrl + ".jpg"} /> <img src={`images/${picUrl}.jpg`} title={tip} /> <a href={url}>去百度</a> </div> }
內嵌樣式要求這樣的語法插值:
style後面直接跟着{{}},沒有引號,{{}}中是JSON,全部的屬性名都是駝峯命名法:
<div style={{"width":"100px","height":"100px","backgroundColor":"red"}}></div>
react的程序,能夠進行合理的換行
<div style={{ "width":"100px", "height":"100px", "backgroundColor":"red" }}> </div>
此時你內心可能有一萬個草泥馬,這是什麼鬼,數組怎麼能不加引號呢?由於是JSX語法規定。
import React from "react"; export default class App extends React.Component { constructor() { super(); } render() { const arr = [ <li key="0">牛奶</li>, <li key="1">咖啡</li>, <li key="2">奶茶</li>, <li key="3">可樂</li> ] return <div> <ul> {arr} </ul> </div> } }
只要你在{}放一個數組,此時這個數組不用循環了,就會自動被展開。
全部的數組元素,必須加上key屬性,不然報錯
注意:
數組有4項,每項都是jsx元素,不須要加引號
每項必需要有不一樣的key屬性,這是react要求的
數組直接{arr}就能夠了,也不須要寫循環遍歷語句。
數據和DOM怎麼進行模板的循環:
arr數組中,沒有任何的標籤,只是數據:此時就要在{}中用map來映射一個新的數組
import React from "react"; export default class App extends React.Component { constructor() { super(); } render() { const arr = ["牛奶","咖啡","奶茶","可樂"] return <div> <ul> {arr.map((item,index)=>{ return <li key={index}>{item}</li> })} </ul> </div> } }
映射出一個表格:
import React from "react"; export default class App extends React.Component { constructor() { super(); } render() { const arr = [ {"id":1,"name":"小明","age":12,"sex":"男"}, {"id":2,"name":"小紅","age":13,"sex":"女"}, {"id":3,"name":"小剛","age":14,"sex":"男"}, {"id":4,"name":"小白","age":15,"sex":"男"} ] return <div> <table> <tbody> { arr.map(item=>{ return <tr key={item.id}> <td>{item.id}</td> <td>{item.name}</td> <td>{item.age}</td> <td>{item.sex}</td> </tr> }) } </tbody> </table> </div> } }
學習的是二維數組的展開
咱們先有一個套路,準備一個外層的數組,而後外層的循環中push內部數組:
import React from "react"; export default class App extends React.Component { //構造函數 constructor() { super(); } render() { var arr = []; for(var i = 1;i <= 9;i++){ var temp = [] for(var j = 1; j <= i; j++) { temp.push(<td key={j}> {i} * {j} = {i*j} </td>) } arr.push(<tr key={i}>{temp}</tr>) } return ( <div> <table> <tbody> {arr} </tbody> </table> </div> ) } };
日曆的原理,決定一個日曆的畫風,有三要素:
這個月第一天是星期幾;
這個月有幾天;
上個月有幾天;
要知道2018年5月5日是星期幾: new Date(2018,5-1,5).getDay() 要知道2018年5月有幾天: new Date(2018,5,0).getDate()
本月有幾天,等價於下個月前一天是幾號,因此下個月的0號,就是本月的最後一天。
給日曆加農曆:
npm install --save solarlunar
import React from "react"; import solarLunar from 'solarLunar'; export default class App extends React.Component { //構造函數 constructor() { super(); } render() { var year = 2018; var month = 8; //是人類的月份,而不是計算機的 //本月第一天是星期幾 var TheMonthFirstDay = new Date(year,month - 1,1).getDay(); //本月共幾天 var TheMonthDays = new Date(year,month,0).getDate(); //上個月共幾天 var prevMonthDays = new Date(year,month-1,0).getDate(); var arr = []; //上個月的尾巴,本月第一天星期幾就有幾天上個月的尾巴 while (TheMonthFirstDay--){ arr.unshift(prevMonthDays--) } // 本月放進數組 var count = 1; while(TheMonthDays--){ arr.push(count++); } // 下個月的前有多少天,要補齊42天 var nextCount = 1; while ( arr.length != 42){ arr.push(nextCount++); } console.log(arr) //接下來要用這個一維數組集合JSX語法,展開爲二維數組 const showTable = ()=>{ var domArr = []; for(var i = 0; i < arr.length / 7; i++){ domArr.push( <tr key={i}> { arr.slice(i * 7, i * 7 + 7).map(item=>{ var n = solarLunar.solar2lunar(year, month, item); return <td key={item}> {item} <br/> {n.term || n.dayCn} </td> }) } </tr> ) } return domArr; } return ( <div> <table> <thead> <tr> <th>日</th> <th>一</th> <th>二</th> <th>三</th> <th>四</th> <th>五</th> <th>六</th> </tr> </thead> <tbody> {showTable()} </tbody> </table> </div> ) } };