
react中文官网:https://zh-hans.reactjs.org/
- React 简介
- 安装
- React文件结构和JSX语法
- 组件
- React State(状态)
- React Props
- 事件处理
- setState 改变react状态
- 动态的添加更改class
- 添加style
- React 条件渲染
- 列表渲染
- React Refs
- 组件生命周期
- 子组件调用父组件方法|向父组件传递参数
- todolist案例
1. React 简介
React 是一个用于构建用户界面的 JAVASCRIPT 库。
React 主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。
React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
React 特点
- 1.声明式设计 −React采用声明范式,可以轻松描述应用。
- 2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
- 3.灵活 −React可以与已知的库或框架很好地配合。
- 4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
- 5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
- 6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
2. 安装
- 安装 node.js
- 安装 create-react-app
这里介绍两种方式,习惯用哪个你自己选
第一种
npm install -g create-react-app ------全局安装create-react-app脚手架
create-react-app myapp
第二种
npx create-react-app myapp
注意⚠️ : npx不是拼写错误,它是npm5.2+ 附带的 package运行工具
上述代码的myapp是项目名,可以自定义

启动项目
cd myreact
yarn start
// npm run start
如果安装了 yarn 优先使用 yarn start
也可以使用 npm run start 启动项目
默认项目地址:http://localhost:3000/

项目目录结构介绍
![]() 目录
|
![]() 解释
|
|---|
或者


3 . React文件结构和JSX语法
a. 第一个react项目
打开 src/App.js 删除默认代码 得到 hello react
import React, { Component } from 'react';
//导入React和 React.Component
class App extends Component {
// App根组件继承 React.compoent
render() {
// 渲染 并返回一段html结构
return (
<div className="App">
<h1>你好react</h1>
</div>
);
}
}
export default App;
//导出默认 App根组件
<div id="demoReact"></div>
<script type="text/babel">
let myDom=<h1>你好世界</h1>
ReactDom.render(myDom,document.getElemenById("demoReact"));
</script>
b. JSX语法
JSX 是一个看起来很像 html 的 JavaScript 语法扩展。
js和html混合
1. 只能有一个根节点
return (
<div className="App">
<h1>你好react</h1>
</div>
);
// Classname="App" 就是根节点
2. 可以执行javascript表达式 {}
{1+1}
{i == 1 ? '对的!' : '错误的'}
3. 类名class 变成 className
<style>
.App{ }
</style>
<div className="App"> xxx </div>
4. 行内样式 展开
var myStyle = {
"font-size": "14px",
"color": "#FF0000"
}
return (
<div className="App">
<h1 style={myStyle}>你好react</h1>
</div>
);
5.注释 '' {/* 注释 */} ''
6. 数组里面可以直接写html节点
var arr = [
<h1>组件渲染</h1>,
<h1>虚拟dom</h1>
]
return (
<div className="App">{arr}</div>
);
7. 列表案例

8. 遍历对象

4. 组件
- 函数组件/无状态组件
- 类组件
什么是组件:
高耦合低内聚 : 高耦合就是把逻辑紧密的内容放在一个组件当中,低内聚就是把不同组件的依赖关系尽量弱化,每个组件尽量独立起来
raact组件分为3个部分,1. 属性:props 2. 状态 state 3. 生命周期
可以这么说,一个 React 应用就是构建在 React 组件之上的。
VScode插件:
- Simple React Snippets
- React Native Tools
a. 创建组件 Child.js
import React,{Component} from 'react'
export default class Child extends Component{
render(){
return (
<div className="child">
<h1>我是子组件</h1>
<hr/>
</div>
);
}
}
b. 调用组件 App.js
import React, { Component } from 'react';
import Child from './components/Child.js' //01. 导入组件
// 导入组件
class App extends Component {
render() {
return (
<div className="App">
<Child/> //02 使用组件
<h1>App根组件</h1>
</div>
);
}
}
export default App;
//导出默认 App根组件
函数组件
<div id="demoReact">
</div>
<script type="text/babel">
function MyCom(){
return(
<div>我是一个函数组件/无状态组件</div>
)
}
let com = <div> //调用组件
<MyCom/>
<MyCom></MyCom>
</div>
ReactDOM.render(com,document.getElementById("demoReact"));
</script>
父子
function MyComA(){
return(
<h1>我是第1个组件</h1>
)
}
function MyComB(){
return(
<h1>我是第2个组件</h1>
)
}
function MyComC(){
return(
<h1>我是第3个组件</h1>
)
}
function Com(){
return(
<div>
<MyComA/>
<MyComB/>
<MyComC/>
</div>
)
}
ReactDOM.render(<Com/>,document.getElementById("demoReact"));
类组件
<div id="demoReact">
</div>
<script type="text/babel">
function MyCom extends React.Component{
render(){
return(
<div>我是类组件</div>
)
}
}
let com = <MyCom/>
ReactDOM.render(com,document.getElementById("demoReact"));
</script>
c. 组件插槽
app.js
import React, { Component, Children } from 'react';
import Child from './components/Child/index.js'
// 导入组件
class App extends Component {
render() {
return (
<div className="App">
<Child><p>插槽</p></Child>
<MyTag>love</MyTag>
</div>
);
}
}
export default App;
//导出默认 App根组件
function MyTag({children}){
//函数组件
return(<h3>函数组件{children}</h3>)
}
index.js
import React,{Component} from 'react'
export default class Child extends Component{
constructor(props){
super(props);
}
render(){
return (
<div className="child">
child内容{this.props.children}
</div>
);
}
}
5. React State(状态)
state 是组件的当前状态,可以把组件简单看成一个“状态机”,根据状态 state 呈现不同的 UI 展示。 一旦状态(数据)更改,组件就会自动调用 render 重新渲染 UI,这个更改的动作会通过 this.setState 方法来触发。
初始化组件 state
添加一个类构造函数来初始化状态 this.state
Child/index.js
import React, { Component } from 'react';
class App extends Component {
constructor() {
super();
this.state={name:"mumu",age:18}
}
render() {
return (
<div className="App">
大家好我是{this.state.name}今年{this.state.age}岁了
</div>
);
}
}
export default App;
6. React Props
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。
传递prop给子组件
App.js
import React, { Component } from 'react';
import Child from './components/Child'
class App extends Component {
render() {
return (
<div className="App">
<Child name="mumu"> </Child>
<Child name="小明"></Child>
<Child ></Child>
</div>
);
}
}
export default App;
Child.js
import React,{Component} from 'react'
export default class Child extends Component{
constructor(props){
super(props);
this.state = {num:1}
}
render(){
return (
<div className="child">
<h1>我是子组件 我的名字是{this.props.name}</h1>
<hr/>
</div>
);
}
}
Child.defaultProps = {
name:"保密"
}
// props 默认属性值
7. 事件处理
React 元素的事件处理和 DOM 元素类似
React 事件绑定属性的命名采用驼峰式写法,而不是小写。
如果采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM 元素的写法)
javascript写法
<button onclick="showMsg()">
按钮
</button>
react写法
<button onClick={showMsg}">
按钮
</button>
完整react代码
import React, { Component } from 'react';
class App extends Component {
showMsg(){
alert("来自react问候!");
}
render() {
return (
<div className="App">
<button onClick={this.showMsg}>按钮</button>
</div>
);
}
}
export default App;
8. setState 改变react状态
用箭头函数是为了保证函数里面this的正确指向br 你也可以用bind方法
按钮加减案例
import React,{Component, Children} from 'react'
export default class Child extends Component{
constructor(props){
super(props);
this.state = {num:1,name:'王大锤'}
}
addNum(n){
let num = this.state.num+n;
this.setState({num:num})
}
render(){
return (
<div className="child">
child内容<br/>
今年我{this.props.age}岁了<br/>
{this.state.name}<br/>
<button onClick={this.addNum.bind(this,2)}>{this.state.num}</button>
<button onClick={()=>this.addNum(-2)}>{this.state.num}</button>
{/*bind(this)指执行addNum让addNum里面的this为当前组件*/}
</div>
);
}
}
React 表单双向绑定
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {num:1}
}
changeNum(e){
this.setState({num:e.target.value})
}
render() {
return (
<div className="App">
<input type="text" value={this.state.num} onChange={this.changeNum.bind(this)}/>
<h1>{this.state.num}</h1>
</div>
);
}
}
export default App;
9. 动态的添加更改class
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {bg:'red'}
}
changeClass(e){
this.setState(pre=>{
return ({bg:pre.bg==='red'?'blue':'red'});
})
}
render() {
return (
<div className="App">
<button className={this.state.bg} onClick={this.changeClass.bind(this)}>按钮</button>
</div>
);
}
}
export default App;
10. 添加style
render() {
var css = {
borderRadius:"6px",
padding:"8px 16px",
color:'#fff',
background:'blue'
}
return (
<div className="App">
<button style={css}>按钮</button>
</div>
);
}
}
11. React 条件渲染
条件性地渲染一块内容
三目运算符号
render() {
var isLogin = true;
return (
<div className="App">
{isLogin?'欢迎您回来主人':'请登陆'}
</div>
);
}
&&运算符
在 JavaScript 中,true && expression 总是返回 expression,而 false && expression 总是返回 false。
因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。
render() {
var isLogin = false;
return (
<div className="App">
{isLogin &&'欢迎您回来主人'}
</div>
);
}
12. 列表渲染
我们可以使用 JavaScript 的 map() 方法来创建列表。
完整代码
import React, { Component } from 'react';
class App extends Component {
constructor(props) { //初始化列表数据
super(props);
this.state={
list:[{name:'vue'},{name:'react'},{name:'angular'}]
}
}
render() {
return (
<div className="App">
{this.state.list.map(
(item,index)=>{
return (
<div key={index}>{item.name}</div>
)
}
)}
</div>
);
}
}
export default App;
Key 可以在 DOM 中的某些元素被增加或删除的时候帮助 React 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。
一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用来自数据的 id 作为元素的 key:
元素没有确定的 id 时,你可以使用他的序列号索引 index 作为 key:
13. React Refs
React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。
你可以通过使用 this 来获取当前 React 组件,或使用 ref 来获取组件的引用
import React, { Component } from 'react';
class App extends Component {
getFocus(){
this.refs.inp.focus();
}
render() {
return (
<div className="App">
<input type="text" ref="inp" />
<button onClick={this.getFocus.bind(this)}>获取焦点</button>
</div>
);
}
}
export default App;
我们也可以使用 getDOMNode()方法获取DOM元素
14. 组件生命周期
一般来说,一个组件类由 extends Component 创建,并且提供一个 render 方法以及其他可选的生命周期函数、组件相关的事件或方法来定义。
一个简单的例子:
import React, { Component } from 'react';
class App extends Component {
getFocus(){
this.refs.inp.focus();
}
render() {
return (
<div className="App">
<input type="text" ref="inp" />
<button onClick={this.getFocus.bind(this)}>获取焦点</button>
</div>
);
}
}
export default App;
getInitialState
初始化 this.state 的值,只在组件装载之前调用一次。
如果是使用 ES6 的语法,你也可以在构造函数中初始化状态,比如:
class Counter extends Component {
constructor(props) {
super(props);
this.state = { num:1 };
}
render() {
// ...
}
}
getDefaultProps
只在组件创建时调用一次并缓存返回的对象(即在 React.createClass 之后就会调用)。
因为这个方法在实例初始化之前调用,所以在这个方法里面不能依赖 this 获取到这个组件的实例。
在组件装载之后,这个方法缓存的结果会用来保证访问 this.props 的属性时,当这个属性没有在父组件中传入(在这个组件的 JSX 属性里设置),也总是有值的。
如果是使用 ES6 语法,可以直接定义 defaultProps 这个类属性来替代,这样能更直观的知道 default props 是预先定义好的对象值:
Child.defaultProps = { name: '保密' };
render
必须
组装生成这个组件的 HTML 结构(使用原生 HTML 标签或者子组件),也可以返回 null 或者 false,这时候 ReactDOM.findDOMNode(this) 会返回 null。
生命周期函数
装载组件触发
componentWillMount
只会在装载之前调用一次,在 render 之前调用,你可以在这个方法里面调用 setState 改变状态,并且不会导致额外调用一次 render
componentDidMount
只会在装载完成之后调用一次,在 render 之后调用,从这里开始可以通过 ReactDOM.findDOMNode(this) 获取到组件的 DOM 节点。
如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
更新组件触发
这些方法不会在首次 render 组件的周期调用
componentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdate
卸载组件触发
componentWillUnmount
更多关于组件相关的方法说明,参见:
完整的代码
import React, {Component } from 'react'
export default class Child extends Component {
constructor(props){
// 组件初始化
super(props);
this.state={date:new Date(),flag:true}
}
// 第一次 渲染完毕 适合 setTimeout interval ajax
componentDidMount(){
this.Id = setInterval(()=>{
this.setState({date:new Date()});
},1000)
}
componentDidUpdate(){
console.log("组件更新");
}
// 组件卸载调用
componentWillUnmount(){
clearInterval(this.Id);
}
switchHd(){
this.setState({flag:!this.state.flag});
}
render() {
return (
<div className="child">
<p>{this.state.flag?<h1>我喜欢冬天的雪</h1>:<h1>我喜欢夏天的风</h1> }</p>
<button onClick={this.switchHd.bind(this)}>切换</button>
</div>
)
}
}
15.子组件调用父组件方法|向父组件传递参数
父亲传一个函数props
import React, { Component } from 'react';
import Child from './components/Child'
class App extends Component {
showMsg(msg){
alert(msg);
}
render() {
return (
<div className="App">
<Child name="kangkang" fun={this.showMsg}></Child>
</div>
);
}
}
export default App;
子组件在箭头函数执行props
import React,{Component} from 'react'
export default class Child extends Component{
render(){
return (
<div className="child">
<h1>我是子组件 我的名字是{this.props.name}</h1>
<button onClick={()=>{this.props.fun('我爱我的祖国')}}>调用父亲函数方法</button>
<hr/>
</div>
);
}
}
16. todolist案例
import React from 'react';
import './App.css';
import {ToDo,Child} from './components'
// 导入todo组件
class App extends React.Component {
constructor(props) {
super(props);
this.state = { msg:'todolist' }
}
changeIt(str){
alert(str);
this.setState({msg:str})
}
render() {
return (
<div className="App" >
<h1>{this.state.msg}</h1>
<ToDo></ToDo>
<Child msg={this.state.msg}></Child>
{/* 使用todo组件 */}
</div>
);
}
}
export default App;
import React, { Component } from 'react';
import './normalize.css'
import './App.css';
class App extends Component {
constructor(props){
super(props);
this.state = {current:'msg',list:[{name:'vue', done:false}, {name:'react', done:false}, {name:'angular', done:true}]}
}
changeHd(e){
// console.log(e.target.value);
this.setState({current:e.target.value})
// react 不会自动更新 手动设置 current的更新
}
addList(){
let oList = this.state.list;
oList.unshift({name:this.state.current, done:false});
this.setState({list:oList,current:''});
}
removeList(item){
let oList = this.state.list;
let index = oList.indexOf(item);
oList.splice(index, 1);
this.setState({list: oList});
}
doneList(item,flag){
let oList = this.state.list;
item.done = flag;
this.setState({list: oList});
}
render() {
return (
<div className="app p15 mt15">
<h1>我的学习清单</h1>
<div className="mt30 row">
<div className="col-80">
<input
type="text"
value={this.state.current}
onChange={this.changeHd.bind(this)}
/>
</div>
<div className="col-20">
<button className="button button-primary" onClick={this.addList.bind(this)}>添加</button>
</div>
</div>
<div className="mt30">未完成</div>
<ul className="mt15">
{ this.state.list.map(
(item, index) => {
if(!item.done){
return (
<li className="item" key={index}>
<span>{item.name}</span>
<button className="button button-clear text-center r" onClick={this.removeList.bind(this,item)}>×</button>
<button className="button button-success button-m button-outline text-center r" onClick={this.doneList.bind(this,item,true)}>完成</button>
</li>
)
}
}
)}
</ul>
<div className="mt30">已完成</div>
<ul className="mt15">
{ this.state.list.map(
// => 返回的内容
// =>() 返回的对象 jxs 格式 ()代表返回一个单一的节点
// =>{ 可以执行一些额为代码 return 返回内容}
(item, index) => {
if(item.done){
return (
<li className="item" key={index}>
<span>{item.name}</span>
<button className="button button-clear text-center r" onClick={this.removeList.bind(this,item)}>×</button>
<button className="button button-outline button-m text-center r" onClick={this.doneList.bind(this,item,false)}>取消</button>
</li>
)
}
}
)}
</ul>
</div>
);
}
}
export default App;
import React, { Component } from 'react';
class ToDo extends Component {
constructor(props) {
super(props);
this.state = {
current:'',
list:[{name:'学习vue',done:true},{name:'学习React',done:false}],
key:'all',
filterList:[{name:'学习vue',done:true},{name:'学习React',done:false}],
// 初始化 filterList和list一致
}
// 设置默认的过滤后列表为全部
// current 当前input的内容
// list 清单列表初始内容
// key 过滤的条件
// filterList 过滤后的列表
}
changeFilterList(str){
this.setState({key:str});
let flist = [];
if(str==='all'){
flist = this.state.list;
// 如果是全部直接返回list
}else if(str==='done'){
flist = this.state.list.filter(item=>item.done)
// 如果是完成 返回已完成的list
}else if(str==='undo'){
flist = this.state.list.filter(item=>!item.done);
}
this.setState({filterList:flist});
// 更新过滤后的列表
}
addList(){
let olist = this.state.list; //获取到之前的list
olist.unshift({name:this.state.current,done:false});
// olist 从前面添加一个数据 ,默认done为false
this.setState({list:olist,current:''});
// 同时更新两个数据 list current清空
}
delItem(item){
let flag = window.confirm("您确定要删除吗?");
// 弹出确认框
if(flag){
let olist = this.state.list; // 拿到list
let ind = olist.indexOf(item); // 后去item对应下标
olist.splice(ind,1); // 从数组删除
this.setState({list:olist}) // 更新数据
}
}
ChangeDone(item){
item.done=!item.done;//让完成效果取反
let list = this.state.list; //获取的list
this.setState(list);
// 更新 list;
}
render() {
return (<div className="todo">
<p><span onClick={this.changeFilterList.bind(this,'all')}>全部</span> | <span onClick={this.changeFilterList.bind(this,'done')}>已完成</span> | <span onClick={this.changeFilterList.bind(this,'undo')}>未完成</span></p>
<input
type="text"
value={this.state.current}
onChange={e=>{this.setState({current:e.target.value})}}
onKeyUp={e=>e.keyCode===13?this.addList():''} />
<button onClick={()=>{this.addList()}}>添加</button>
{/* 表单的双向绑定 value 绑定, Input事件绑定*/}
{/* 实现添加列表 */}
{/* enter键添加 enter的keyCode是13 事件OnKeyUp */}
<div className="list">
{
this.state.filterList.map((item,index)=>{
return (<div key={index} className={item.done?'gray':''}> {/* 更具Item的done属性动态添加class */}
{item.name}
<button onClick={this.ChangeDone.bind(this,item)}>{item.done?'取消':'完成'}</button>
{/* 单击时候 修改完成状态 和按钮文字 */}
<span onClick={(e,item)=>this.delItem(item)}>×</span>
</div>)
})
}
{/* 实现完成 */}
{/* 动态class */}
{/* 删除功能 */}
{/* key 是dom识别标识符 优化渲染 */}
{/* map函数是数组映射函数 一一对应返回div标签数组 */}
</div>
</div>);
}
}
export default ToDo;
// 创建并导出todo组件

