官网: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> ) } };