React

一、React

尚硅谷

React学习视频:尚硅谷学习视频

尚硅谷:
http://www.atguigu.com/

Vue学习视频(尚硅谷):
https://www.bilibili.com/video/BV1wy4y1D7JT?p=1

百度云课件(尚硅谷资料):
链接:https://pan.baidu.com/s/1vl8_1fcbOX3LM6rwxTY1Pg 
提取码:duhm

gitee笔记项目:
https://gitee.com/happy_sad/react

React官网:
https://react.dev/

React中文官网:
https://react.docschina.org/

Fetch:
https://github.github.io/fetch/

segmentfault 思否:
https://segmentfault.com/

Ant Design:
https://ant.design/docs/react/introduce-cn

material-ui:
https://mui.com/material-ui/getting-started/overview/

一、react_basic

一、hello_react

DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>hello_reacttitle>
head>

<body>
	
	<div id="test">div>
	
	<script type="text/javascript" src="../js/react.development.js">script>
	
	<script type="text/javascript" src="../js/react-dom.development.js">script>
	
	<script type="text/javascript" src="../js/babel.min.js">script>

	
	<script type="text/babel">
		// 1.创建虚拟DOM(JSX)
		const VDOM = <h1>Hello,React</h1>/* 不要写引号,因为不是字符串 */
		// 2.渲染虚拟DOM到页面
		ReactDOM.render(VDOM, document.getElementById('test'))
	script>
body>

html>

二、虚拟DOM的两种创建方式

1、使用jsx创建虚拟DOM
DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>01_使用jsx创建虚拟DOMtitle>
head>

<body>
	
	<div id="test">div>
	
	<script type="text/javascript" src="../js/react.development.js">script>
	
	<script type="text/javascript" src="../js/react-dom.development.js">script>
	
	<script type="text/javascript" src="../js/babel.min.js">script>

	
	<script type="text/babel">
		// 1.创建虚拟DOM(JSX)
		const VDOM = (				/* 不要写引号,因为不是字符串 */
			<h1 id="title">
				<span>Hello,React</span>
			</h1>
		)
		// 2.渲染虚拟DOM到页面
		ReactDOM.render(VDOM, document.getElementById('test'))
	script>
body>

html>
2、使用js创建虚拟DOM
DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>02_使用js创建虚拟DOMtitle>
head>

<body>
	
	<div id="test">div>
	
	<script type="text/javascript" src="../js/react.development.js">script>
	
	<script type="text/javascript" src="../js/react-dom.development.js">script>

	
	<script type="text/javascript">
		// 1.创建虚拟DOM(JS)
		const VDOM = React.createElement('h1', { id: 'title' }, React.createElement('span', {}, 'Hello,React'))
		// 2.渲染虚拟DOM到页面
		ReactDOM.render(VDOM, document.getElementById('test'))
	script>
body>

html>
3、虚拟DOM和真实DOM
DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>03_虚拟DOM和真实DOMtitle>
head>

<body>
	
	<div id="test">div>
	<div id="demo">div>
	
	<script type="text/javascript" src="../js/react.development.js">script>
	
	<script type="text/javascript" src="../js/react-dom.development.js">script>
	
	<script type="text/javascript" src="../js/babel.min.js">script>

	
	<script type="text/babel">
		// 1.创建虚拟DOM(JSX)
		const VDOM = (				/* 不要写引号,因为不是字符串 */
			<h1 id="title">
				<span>Hello,React</span>
			</h1>
		)
		// 2.渲染虚拟DOM到页面
		ReactDOM.render(VDOM, document.getElementById('test'))

		console.log('虚拟DOM', VDOM);
		console.log('虚拟DOM类型', typeof VDOM);
		console.log('虚拟DOM对象', VDOM instanceof Object);

		const TDOM = document.getElementById('demo')
		console.log('真实DOM', TDOM);
		console.log('真实DOM类型', typeof TDOM);
		console.log('真实DOM对象', TDOM instanceof Object);

		/*
			关于虚拟DOM:
			1.本质是Object类型的对象(一般对象)
			2.虚拟DOM比较‘轻’,真实DOM比较‘重’,因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性
			3.虚拟DOM最终会被React转化为真实DOM,呈现在页面上
		*/
	script>
body>

html>

三、jsx语法规则

DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>jsx语法规则title>
	<style>
		.title {
			background-color: orange;
			width: 200px;
		}
	style>
head>

<body>
	
	<div id="test">div>
	
	<script type="text/javascript" src="../js/react.development.js">script>
	
	<script type="text/javascript" src="../js/react-dom.development.js">script>
	
	<script type="text/javascript" src="../js/babel.min.js">script>

	
	<script type="text/babel">
		const myId = 'aTgUigu'
		const myData = 'HeLlo,rEaCt'
		// 1.创建虚拟DOM(JSX)
		const VDOM = (
			<div>
				<h2 className="title" id={myId.toLowerCase()}>
					<span style={{ color: 'white', fontSize: '29px' }}>{myData.toLowerCase()}</span>
				</h2>
				<h2 className="title" id={myId.toUpperCase()}>
					<span style={{ color: 'white', fontSize: '29px' }}>{myData.toUpperCase()}</span>
				</h2>
				<input type="text"></input>
				<Good></Good>
			</div>
		)
		// 2.渲染虚拟DOM到页面
		ReactDOM.render(VDOM, document.getElementById('test'))


		/*
			jsx语法规则:
			1.定义虚拟DOM时,不要写引号
			2.标签中混入JS表达式时要用{}
			3.样式的类名指定不要用class,要用className
			4.内联样式,要用style={{key:'value'}}的形式去写
			5.虚拟DOM必须只有一个根标签
			6.标签必须闭合
			7.标签首字母
				(1).若小写字母开头,则将该标签转为html同名元素,若html中无该标签对应的同名元素,则报错(123)
				(2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错
		*/
	script>
body>

html>

四、jsx小练习

DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>jsx小练习title>
head>

<body>
	
	<div id="test">div>
	
	<script type="text/javascript" src="../js/react.development.js">script>
	
	<script type="text/javascript" src="../js/react-dom.development.js">script>
	
	<script type="text/javascript" src="../js/babel.min.js">script>

	
	<script type="text/babel">
		// 模拟数据
		const data1 = ['Angular', 'React', 'Vue']
		// const data2 = [
  • Angular
  • ,
  • React
  • ,
  • Vue
  • ]
    // 1.创建虚拟DOM(JSX) const VDOM = ( <div> <h1>前端js框架列表</h1> <ul> { data1.map((item, index) => { return <li key={index}>{item}</li> }) } </ul> </div> ) // const VDOM = ( //
    //

    前端js框架列表

    //
      // {data2} //
    //
    // ) // 2.渲染虚拟DOM到页面 ReactDOM.render(VDOM, document.getElementById('test')) /* 注:【js语句(代码)】与【js表达式】 1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方 下面这些都是表达式: (1).a (2).a+b (3).demo(1) (4).arr.map() (5).function test(){} 2.语句(代码): 下面这些就是语句(代码): (1).if() (2).for() (3).switch(){case:xxx} */
    script> body> html>

    五、react中定义组件

    1、函数式组件
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_函数式组件title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//1.创建函数式组件
    		function MyComponent () {
    			console.log(this); //此处的this是undefined,因为babel编译后开启了严格模式
    			return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
    		}
    		//2.渲染组件到页面
    		ReactDOM.render(<MyComponent></MyComponent>, document.getElementById('test'))
    		/*
    			执行了ReactDOM.render(.......之后,发生了什么?
    					1.React解析组件标签,找到了MyComponent组件。
    					2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。
    		*/
    	script>
    body>
    
    html>
    
    2、类式组件
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_类式组件title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//1.创建类式组件
    		class MyComponent extends React.Component {
    			render () {
    				//render是放在哪里的?—— MyComponent的原型对象上,供实例使用。
    				//render中的this是谁?—— MyComponent的实例对象 <=> MyComponent组件实例对象。
    				console.log('render中的this:', this);
    				return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
    			}
    		}
    		//2.渲染组件到页面
    		ReactDOM.render(<MyComponent></MyComponent>, document.getElementById('test'))
    		/*
    			执行了ReactDOM.render(.......之后,发生了什么?
    					1.React解析组件标签,找到了MyComponent组件。
    					2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
    					3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
    		*/
    	script>
    body>
    
    html>
    

    六、组件实例三大属性state

    1、state
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_statetitle>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//1.创建组件
    		class Weather extends React.Component {
    
    			//构造器调用几次? ———— 刷新初始化页面时调用,1次
    			constructor(props) {
    				console.log('constructor', props);
    				super(props)
    				//初始化状态
    				this.state = { isHot: false, wind: '微风' }
    				//解决changeWeather中this指向问题(挂载实例对象)
    				this.changeWeatherMount = this.changeWeatherPro.bind(this)
    			}
    
    			//render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
    			render () {
    				console.log('render');
    				//读取状态
    				const isHot = this.state.isHot;
    				const wind = this.state.wind;
    				// const { isHot, wind } = this.state;
    				return <h1 onClick={this.changeWeatherMount}>今天天气很{isHot ? '炎热' : '凉爽'}{wind}</h1>
    			}
    
    			//changeWeather调用几次? ———— n次 点几次调几次(放在原型上的)
    			changeWeatherPro () {
    				//changeWeather放在哪里? ———— Weather的原型对象上,供实例使用
    				//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
    				//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
    
    				console.log('changeWeatherPro');
    				//获取原来的isHot值
    				const isHot = this.state.isHot
    				//严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。
    				this.setState({ isHot: !isHot })
    				if (this.state.isHot) {
    					this.setState({ wind: '微风' })
    				} else {
    					this.setState({ wind: '台风' })
    				}
    				console.log('this', this);
    
    				//严重注意:状态(state)不可直接更改,下面这行就是直接更改!!!
    				//this.state.isHot = !isHot //这是错误的写法
    			}
    		}
    		//2.渲染组件到页面
    		ReactDOM.render(<Weather></Weather>, document.getElementById('test'))
    
    		// const w= new Weather();
    		// w.changeWeather();
    
    	script>
    body>
    
    html>
    
    2、state的简写方式
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_state的简写方式title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//1.创建组件
    		class Weather extends React.Component {
    			//01初始化状态(简写,不需要在construct中定义this.state)
    			state = { isHot: false, wind: '微风' }
    
    			render () {
    				const { isHot, wind } = this.state
    				return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}{wind}</h1>
    			}
    
    			//02自定义方法————要用赋值语句的形式+箭头函数(简写,不需要在construct中挂载实例对象)
    			// 箭头函数没有自己的this,它的this是往外层查找的this
    			changeWeather = () => {
    				const isHot = this.state.isHot
    				this.setState({ isHot: !isHot })
    				if (this.state.isHot) {
    					this.setState({ wind: '微风' })
    				} else {
    					this.setState({ wind: '台风' })
    				}
    				console.log('this', this);
    			}
    		}
    		//2.渲染组件到页面
    		ReactDOM.render(<Weather></Weather>, document.getElementById('test'))
    
    	script>
    body>
    
    html>
    

    七、组件实例三大属性props

    1、props基本使用
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_props基本使用title>
    head>
    
    <body>
    	
    	<div id="test1">div>
    	<div id="test2">div>
    	<div id="test3">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Person extends React.Component {
    			render () {
    				console.log('this', this);
    				// return (
    				// 	
      //
    • 姓名:{this.props.name}
    • //
    • 性别:{this.props.sex}
    • //
    • 年龄:{this.props.age + 1}
    • //
    // ) const { name, age, sex } = this.props return ( <ul> <li>姓名:{name}</li> <li>性别:{sex}</li> <li>年龄:{age + 1}</li> </ul> ) } } //渲染组件到页面 ReactDOM.render(<Person name="Ling" age={17} sex="女" />, document.getElementById('test1')) ReactDOM.render(<Person name="Jin" age={18} sex="男"></Person>, document.getElementById('test2')) const p = { name: 'Yu', age: 18, sex: '女' } console.log('@', { ...p }); // ReactDOM.render(,document.getElementById('test3')) ReactDOM.render(<Person {...p} ></Person>, document.getElementById('test3'))
    script> body> html>
    2、对props进行限制
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_对props进行限制title>
    head>
    
    <body>
    	
    	<div id="test1">div>
    	<div id="test2">div>
    	<div id="test3">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    	
    	<script type="text/javascript" src="../js/prop-types.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Person extends React.Component {
    			render () {
    				// console.log(this);
    				const { name, age, sex } = this.props
    				//props是只读的
    				//this.props.name = 'jack' //此行代码会报错,因为props是只读的
    				return (
    					<ul>
    						<li>姓名:{name}</li>
    						<li>性别:{sex}</li>
    						<li>年龄:{age + 1}</li>
    					</ul>
    				)
    			}
    		}
    		//对标签属性进行类型、必要性的限制
    		Person.propTypes = {
    			name: PropTypes.string.isRequired, //限制name必传,且为字符串
    			sex: PropTypes.string,//限制sex为字符串
    			age: PropTypes.number,//限制age为数值
    			speak: PropTypes.func,//限制speak为函数
    		}
    		//指定默认标签属性值
    		Person.defaultProps = {
    			sex: '男',//sex默认值为男
    			age: 18 //age默认值为18
    		}
    		//渲染组件到页面
    		ReactDOM.render(<Person name={100} speak={speak} />, document.getElementById('test1'))
    		ReactDOM.render(<Person name="tom" age={18} sex="女"></Person>, document.getElementById('test2'))
    
    		const p = { name: '老刘', age: 18, sex: '女' }
    		// console.log('@',...p);
    		// ReactDOM.render(,document.getElementById('test3'))
    		ReactDOM.render(<Person {...p}></Person>, document.getElementById('test3'))
    
    		function speak () {
    			console.log('我说话了');
    		}
    	script>
    body>
    
    html>
    
    3、props的简写方式
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>03_props的简写方式title>
    head>
    
    <body>
    	
    	<div id="test1">div>
    	<div id="test2">div>
    	<div id="test3">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    	
    	<script type="text/javascript" src="../js/prop-types.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Person extends React.Component {
    
    			constructor(props) {
    				//构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
    				// console.log(props);
    				super(props)
    				console.log('constructor', this.props);
    			}
    
    			//对标签属性进行类型、必要性的限制
    			static propTypes = {
    				name: PropTypes.string.isRequired, //限制name必传,且为字符串
    				sex: PropTypes.string,//限制sex为字符串
    				age: PropTypes.number,//限制age为数值
    			}
    
    			//指定默认标签属性值
    			static defaultProps = {
    				sex: '男',//sex默认值为男
    				age: 18 //age默认值为18
    			}
    
    			render () {
    				// console.log(this);
    				const { name, age, sex } = this.props
    				//props是只读的
    				//this.props.name = 'jack' //此行代码会报错,因为props是只读的
    				return (
    					<ul>
    						<li>姓名:{name}</li>
    						<li>性别:{sex}</li>
    						<li>年龄:{age + 1}</li>
    					</ul>
    				)
    			}
    		}
    
    		//渲染组件到页面
    		ReactDOM.render(<Person name="jerry" />, document.getElementById('test1'))
    	script>
    body>
    
    html>
    
    4、函数组件使用props
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>04_函数组件使用propstitle>
    head>
    
    <body>
    	
    	<div id="test1">div>
    	<div id="test2">div>
    	<div id="test3">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    	
    	<script type="text/javascript" src="../js/prop-types.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		function Person (props) {
    			console.log("props", props)
    			const { name, age, sex } = props
    			return (
    				<ul>
    					<li>姓名:{name}</li>
    					<li>性别:{sex}</li>
    					<li>年龄:{age}</li>
    				</ul>
    			)
    		}
    		Person.propTypes = {
    			name: PropTypes.string.isRequired, //限制name必传,且为字符串
    			sex: PropTypes.string,//限制sex为字符串
    			age: PropTypes.number,//限制age为数值
    		}
    
    		//指定默认标签属性值
    		Person.defaultProps = {
    			sex: '男',//sex默认值为男
    			age: 18 //age默认值为18
    		}
    		//渲染组件到页面
    		ReactDOM.render(<Person name="jerry" />, document.getElementById('test1'))
    	script>
    body>
    
    html>
    

    八、组件实例三大属性refs

    1、字符串形式的ref
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_字符串形式的reftitle>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Demo extends React.Component {
    			//展示左侧输入框的数据
    			//  
    			// showData = () => {
    			// 	const input11 = document.getElementById("input11")
    			// 	alert(input11.value)
    			// }
    			showData = () => {
    				console.log(this.refs.input1)
    				// const input1 = this.refs.input1
    				const { input1 } = this.refs
    				alert(input1.value)
    			}
    			//展示右侧输入框的数据
    			showData2 = () => {
    				console.log(this.refs.input2)
    				const { input2 } = this.refs
    				alert(input2.value)
    			}
    			render () {
    				return (
    					<div>
    						<input ref="input1" type="text" placeholder="点击按钮提示数据" />&nbsp;
    						<button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
    						<input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
    					</div>
    				)
    			}
    		}
    		//渲染组件到页面
    		ReactDOM.render(<Demo></Demo>, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    2、回调函数形式的ref
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_回调函数形式的reftitle>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Demo extends React.Component {
    			//展示左侧输入框的数据
    			showData = () => {
    				const { input1 } = this
    				alert(input1.value)
    			}
    			//展示右侧输入框的数据
    			showData2 = () => {
    				const { input2 } = this
    				alert(input2.value)
    			}
    			render () {
    				return (
    					<div>
    						{/*{console.log(currentNode);}} type="text" placeholder="点击按钮提示数据" /> */}
    						<input ref={(currentNode) => { this.input1 = currentNode; }} type="text" placeholder="点击按钮提示数据" />&nbsp;
    						<button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
    						<input onBlur={this.showData2} ref={c => this.input2 = c} type="text" placeholder="失去焦点提示数据" />&nbsp;
    					</div>
    				)
    			}
    		}
    		//渲染组件到页面
    		ReactDOM.render(<Demo a="1" b="2" />, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    3、回调ref中回调执行次数的问题
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>03_回调ref中回调执行次数的问题title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Demo extends React.Component {
    
    			state = { isHot: false }
    
    			showInfo = () => {
    				const { input1 } = this
    				alert(input1.value)
    			}
    
    			changeWeather = () => {
    				//获取原来的状态
    				const { isHot } = this.state
    				//更新状态
    				this.setState({ isHot: !isHot })
    			}
    
    			saveInput = (c) => {
    				this.input1 = c;
    				console.log('@', c);
    			}
    
    			render () {
    				const { isHot } = this.state
    				return (
    					<div>
    						<h2>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
    						{/*{this.input1 = c;console.log('@',c);}} type="text"/>

    */
    } <input ref={this.saveInput} type="text" /><br /><br /> <button onClick={this.showInfo}>点我提示输入的数据</button> <button onClick={this.changeWeather}>点我切换天气</button> </div> ) } } //渲染组件到页面 ReactDOM.render(<Demo />, document.getElementById('test'))
    script> body> html>
    4、createRef的使用
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>04_createRef的使用title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Demo extends React.Component {
    			/* 
    				React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的
    			 */
    			myRef = React.createRef()
    			myRef2 = React.createRef()
    			//展示左侧输入框的数据
    			showData = () => {
    				alert(this.myRef.current.value);
    			}
    			//展示右侧输入框的数据
    			showData2 = () => {
    				alert(this.myRef2.current.value);
    			}
    			render () {
    				return (
    					<div>
    						<input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />&nbsp;
    						<button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
    						<input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据" />&nbsp;
    					</div>
    				)
    			}
    		}
    		//渲染组件到页面
    		ReactDOM.render(<Demo a="1" b="2" />, document.getElementById('test'))
    	script>
    body>
    
    html>
    

    九、react中的事件处理

    DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>事件处理title>
    head>
    <body>
    	
    	<div id="test">div>
    	
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Demo extends React.Component{
    			/* 
    				(1).通过onXxx属性指定事件处理函数(注意大小写)
    						a.React使用的是自定义(合成)事件, 而不是使用的原生DOM事件 —————— 为了更好的兼容性
    						b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) ————————为了的高效
    				(2).通过event.target得到发生事件的DOM元素对象 ——————————不要过度使用ref
    			 */
    			//创建ref容器
    			myRef = React.createRef()
    			myRef2 = React.createRef()
    
    			//展示左侧输入框的数据
    			showData = (event)=>{
    				console.log(event.target);
    				alert(this.myRef.current.value);
    			}
    
    			//展示右侧输入框的数据
    			showData2 = (event)=>{
    				alert(event.target.value);
    			}
    
    			render(){
    				return(
    					<div>
    						<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>&nbsp;
    						<button onClick={this.showData}>点我提示左侧的数据</button>&nbsp;
    						<input onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>&nbsp;
    					</div>
    				)
    			}
    		}
    		//渲染组件到页面
    		ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
    	script>
    body>
    html>
    

    十、react中收集表单数据

    1、非受控组件
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_非受控组件title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Login extends React.Component {
    			handleSubmit = (event) => {
    				event.preventDefault() //阻止表单提交
    				const { username, password } = this
    				alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
    			}
    			render () {
    				return (
    					<form action="http://www.atguigu.com" onSubmit={this.handleSubmit}>
    						用户名:<input ref={c => this.username = c} type="text" name="username" />
    						密码:<input ref={c => this.password = c} type="password" name="password" />
    						<button>登录</button>
    					</form>
    				)
    			}
    		}
    		//渲染组件
    		ReactDOM.render(<Login />, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    2、受控组件
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_受控组件title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Login extends React.Component {
    
    			//初始化状态
    			state = {
    				username: '', //用户名
    				password: '' //密码
    			}
    
    			//保存用户名到状态中
    			saveUsername = (event) => {
    				console.log("saveUsername")
    				this.setState({ username: event.target.value })
    			}
    
    			//保存密码到状态中
    			savePassword = (event) => {
    				console.log("savePassword")
    				this.setState({ password: event.target.value })
    			}
    
    			//表单提交的回调
    			handleSubmit = (event) => {
    				event.preventDefault() //阻止表单提交
    				const { username, password } = this.state
    				alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
    			}
    
    			render () {
    				return (
    					<form action="http://www.atguigu.com" onSubmit={this.handleSubmit}>
    						用户名:<input onChange={this.saveUsername} type="text" name="username" />
    						密码:<input onChange={this.savePassword} type="password" name="password" />
    						<button>登录</button>
    					</form>
    				)
    			}
    		}
    		//渲染组件
    		ReactDOM.render(<Login />, document.getElementById('test'))
    	script>
    body>
    
    html>
    

    十一、高阶函数_函数柯里化

    1、高阶函数_函数柯里化
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_高阶函数_函数柯里化title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//#region 
    		/* 
    			高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。
    							1.若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
    							2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
    							常见的高阶函数有:Promise、setTimeout、arr.map()等等
    
    			函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。 
    				function sum(a){
    					return(b)=>{
    						return (c)=>{
    							return a+b+c
    						}
    					}
    				}
    			*/
    		//#endregion
    		//创建组件
    		class Login extends React.Component {
    			//初始化状态
    			state = {
    				username: '', //用户名
    				password: '' //密码
    			}
    
    			//保存表单数据到状态中
    			saveFormData = (dataType) => {
    				// console.log('dataType:' + dataType)
    				return (event) => {
    					this.setState({ [dataType]: event.target.value })
    				}
    			}
    
    			//表单提交的回调
    			handleSubmit = (event) => {
    				event.preventDefault() //阻止表单提交
    				const { username, password } = this.state
    				alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
    			}
    			render () {
    				return (
    					<form onSubmit={this.handleSubmit}>
    						用户名:<input onChange={this.saveFormData('username')} type="text" name="username" />
    						密码:<input onChange={this.saveFormData('password')} type="password" name="password" />
    						<button>登录</button>
    					</form>
    				)
    			}
    		}
    		//渲染组件
    		ReactDOM.render(<Login />, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    2、不用函数柯里化的实现
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_不用函数柯里化的实现title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Login extends React.Component {
    			//初始化状态
    			state = {
    				username: '', //用户名
    				password: '' //密码
    			}
    
    			//保存表单数据到状态中
    			saveFormData = (dataType, event) => {
    				this.setState({ [dataType]: event.target.value })
    			}
    
    			//表单提交的回调
    			handleSubmit = (event) => {
    				event.preventDefault() //阻止表单提交
    				const { username, password } = this.state
    				alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
    			}
    			render () {
    				return (
    					<form onSubmit={this.handleSubmit}>
    						用户名:<input onChange={(event) => { this.saveFormData('username', event); }} type="text" name="username" />
    						密码:<input onChange={event => this.saveFormData('password', event)} type="password" name="password" />
    						<button>登录</button>
    					</form>
    				)
    			}
    		}
    		//渲染组件
    		ReactDOM.render(<Login />, document.getElementById('test'))
    	script>
    body>
    
    html>
    

    十二、组件的生命周期

    1、引出生命周期
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_引出生命周期title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		//生命周期回调函数 <=> 生命周期钩子函数 <=> 生命周期函数 <=> 生命周期钩子
    		class Life extends React.Component {
    
    			state = { opacity: 1 }
    
    			death = () => {
    				//卸载组件
    				ReactDOM.unmountComponentAtNode(document.getElementById('test'))
    			}
    
    			//组件挂完毕(组件挂载在页面之后调用)
    			componentDidMount () {
    				console.log('componentDidMount');
    				this.timer = setInterval(() => {
    					//获取原状态(此处不可用const,因为使用const后不可更改)
    					// let声明的变量可以改变,值和类型都可以改变;而const声明的常量不可以改变,这意味着,const一旦声明,就必须立即初始化,不能以后再赋值
    					let { opacity } = this.state
    					//减小0.1
    					opacity -= 0.1
    					if (opacity <= 0) opacity = 1
    					//设置新的透明度
    					this.setState({ opacity })
    				}, 200);
    			}
    
    			//组件将要卸载
    			componentWillUnmount () {
    				console.log('componentWillUnmount');
    				//清除定时器
    				clearInterval(this.timer)
    			}
    
    			//初始化渲染、状态更新之后
    			render () {
    				console.log('render');
    				return (
    					<div>
    						<h2 style={{ opacity: this.state.opacity }}>React学不会怎么办?</h2>
    						<button onClick={this.death}>不活了</button>
    					</div>
    				)
    			}
    		}
    		//渲染组件
    		ReactDOM.render(<Life />, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    2、react生命周期(旧)
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_react生命周期(旧)title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		/* 
    				1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
    									1.	constructor()
    									2.	componentWillMount()
    									3.	render()
    									4.	componentDidMount() =====> 常用
    													一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
    				2. 更新阶段: 由组件内部this.setSate()或父组件render触发
    									1.	shouldComponentUpdate()
    									2.	componentWillUpdate()
    									3.	render() =====> 必须使用的一个
    									4.	componentDidUpdate()
    				3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    									1.	componentWillUnmount()  =====> 常用
    													一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
    		*/
    		//创建组件
    		class Count extends React.Component {
    
    			//构造器
    			constructor(props) {
    				console.log('11---Count---constructor');
    				super(props)
    				//初始化状态
    				this.state = { count: 0 }
    			}
    
    			//加1按钮的回调
    			add = () => {
    				//获取原状态
    				const { count } = this.state
    				//更新状态
    				this.setState({ count: count + 1 })
    			}
    
    			//卸载组件按钮的回调
    			death = () => {
    				ReactDOM.unmountComponentAtNode(document.getElementById('test'))
    			}
    
    			//强制更新按钮的回调
    			force = () => {
    				console.log('31---Count---forceUpdate')
    				this.forceUpdate()
    			}
    
    			//组件将要挂载的钩子
    			componentWillMount () {
    				console.log('12---Count---componentWillMount');
    			}
    
    			//组件挂载完毕的钩子
    			componentDidMount () {
    				console.log('14---Count---componentDidMount');
    			}
    
    			//组件将要卸载的钩子
    			componentWillUnmount () {
    				console.log('41---Count---componentWillUnmount');
    			}
    
    			//控制组件更新的“阀门”(需要返回true打开阀门,返回false的话不执行+1)
    			shouldComponentUpdate () {
    				console.log('21---Count---shouldComponentUpdate');
    				return true
    			}
    
    			//组件将要更新的钩子
    			componentWillUpdate () {
    				console.log('22、32---Count---componentWillUpdate');
    			}
    
    			//组件更新完毕的钩子
    			componentDidUpdate () {
    				console.log('24、34---Count---componentDidUpdate');
    			}
    
    			render () {
    				console.log('13、23、33---Count---render');
    				const { count } = this.state
    				return (
    					<div>
    						<h2>当前求和为:{count}</h2>
    						<button onClick={this.add}>点我+1</button>
    						<button onClick={this.death}>卸载组件</button>
    						<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
    					</div>
    				)
    			}
    		}
    
    		//父组件A
    		class A extends React.Component {
    			//初始化状态
    			state = { carName: '奔驰' }
    
    			changeCar = () => {
    				this.setState({ carName: '奥拓' })
    			}
    
    			render () {
    				return (
    					<div>
    						<div>我是A组件</div>
    						<button onClick={this.changeCar}>换车</button>
    						<B carName={this.state.carName} />
    					</div>
    				)
    			}
    		}
    
    		//子组件B
    		class B extends React.Component {
    			//组件将要接收新的props的钩子
    			componentWillReceiveProps (props) {
    				console.log('41---B---componentWillReceiveProps', props);
    			}
    
    			//控制组件更新的“阀门”
    			shouldComponentUpdate () {
    				console.log('42---B---shouldComponentUpdate');
    				return true
    			}
    			//组件将要更新的钩子
    			componentWillUpdate () {
    				console.log('44---B---componentWillUpdate');
    			}
    
    			//组件更新完毕的钩子
    			componentDidUpdate () {
    				console.log('45---B---componentDidUpdate');
    			}
    
    			render () {
    				console.log('43---B---render');
    				return (
    					<div>我是B组件,接收到的车是:{this.props.carName}</div>
    				)
    			}
    		}
    
    		//渲染组件Count/A
    		ReactDOM.render(<Count />, document.getElementById('test'))
    		// ReactDOM.render(, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    3、react生命周期(旧)图

    React_第1张图片

    4、react生命周期(新1)
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>03_react生命周期(新1)title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/17.0.1/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/babel.min.js">script>
    
    	<script type="text/babel">
    		/* 
    				1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
    									1.	constructor()
    									2.	UNSAFE_componentWillMount()
    									3.	render()
    									4.	componentDidMount() =====> 常用
    													一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
    				2. 更新阶段: 由组件内部this.setSate()或父组件render触发
    									1.	shouldComponentUpdate()
    									2.	UNSAFE_componentWillUpdate()
    									3.	render() =====> 必须使用的一个
    									4.	componentDidUpdate()
    				3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    									1.	componentWillUnmount()  =====> 常用
    													一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
    		*/
    		//创建组件
    		class Count extends React.Component {
    
    			//构造器
    			constructor(props) {
    				console.log('11---Count---constructor');
    				super(props)
    				//初始化状态
    				this.state = { count: 0 }
    			}
    
    			//加1按钮的回调
    			add = () => {
    				//获取原状态
    				const { count } = this.state
    				//更新状态
    				this.setState({ count: count + 1 })
    			}
    
    			//卸载组件按钮的回调
    			death = () => {
    				ReactDOM.unmountComponentAtNode(document.getElementById('test'))
    			}
    
    			//强制更新按钮的回调
    			force = () => {
    				console.log('31---Count---forceUpdate')
    				this.forceUpdate()
    			}
    
    			//组件将要挂载的钩子
    			UNSAFE_componentWillMount () {
    				console.log('12---Count---UNSAFE_componentWillMount');
    			}
    
    			//组件挂载完毕的钩子
    			componentDidMount () {
    				console.log('14---Count---componentDidMount');
    			}
    
    			//组件将要卸载的钩子
    			componentWillUnmount () {
    				console.log('15、25、35---Count---UNSAFE_componentWillUnmount');
    			}
    
    			//控制组件更新的“阀门”(需要返回true打开阀门,返回false的话不执行+1)
    			shouldComponentUpdate () {
    				console.log('21---Count---shouldComponentUpdate');
    				return true
    			}
    
    			//组件将要更新的钩子
    			UNSAFE_componentWillUpdate () {
    				console.log('22、32---Count---UNSAFE_componentWillUpdate');
    			}
    
    			//组件更新完毕的钩子
    			componentDidUpdate () {
    				console.log('24、34---Count---componentDidUpdate');
    			}
    
    			render () {
    				console.log('13、23、33---Count---render');
    				const { count } = this.state
    				return (
    					<div>
    						<h2>当前求和为:{count}</h2>
    						<button onClick={this.add}>点我+1</button>
    						<button onClick={this.death}>卸载组件</button>
    						<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
    					</div>
    				)
    			}
    		}
    
    		//父组件A
    		class A extends React.Component {
    			//初始化状态
    			state = { carName: '奔驰' }
    
    			changeCar = () => {
    				this.setState({ carName: '奥拓' })
    			}
    
    			render () {
    				return (
    					<div>
    						<div>我是A组件</div>
    						<button onClick={this.changeCar}>换车</button>
    						<B carName={this.state.carName} />
    					</div>
    				)
    			}
    		}
    
    		//子组件B
    		class B extends React.Component {
    			//组件将要接收新的props的钩子
    			UNSAFE_componentWillReceiveProps (props) {
    				console.log('41---B---UNSAFE_componentWillReceiveProps', props);
    			}
    
    			//控制组件更新的“阀门”
    			shouldComponentUpdate () {
    				console.log('42---B---shouldComponentUpdate');
    				return true
    			}
    			//组件将要更新的钩子
    			UNSAFE_componentWillUpdate () {
    				console.log('44---B---UNSAFE_componentWillUpdate');
    			}
    
    			//组件更新完毕的钩子
    			componentDidUpdate () {
    				console.log('45---B---componentDidUpdate');
    			}
    
    			render () {
    				console.log('43---B---render');
    				return (
    					<div>我是B组件,接收到的车是:{this.props.carName}</div>
    				)
    			}
    		}
    
    		//渲染组件Count/A
    		ReactDOM.render(<Count />, document.getElementById('test'))
    		// ReactDOM.render(, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    5、react生命周期(新2)
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>03_react生命周期(新2)title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/17.0.1/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/babel.min.js">script>
    
    	<script type="text/babel">
    		//创建组件
    		class Count extends React.Component {
    			/* 
    				1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
    									1.	constructor()
    									2.	getDerivedStateFromProps
    									3.	render()
    									4.	componentDidMount() =====> 常用
    													一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
    				2. 更新阶段: 由组件内部this.setSate()或父组件render触发
    									1.	getDerivedStateFromProps
    									2.	shouldComponentUpdate
    									3.	render() =====> 必须使用的一个
    									4.	getSnapshotBeforeUpdate
    									5.  componentDidUpdate
    				3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    									1.	componentWillUnmount()  =====> 常用
    													一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
    		*/
    			//构造器
    			constructor(props) {
    				console.log('11---Count---constructor');
    				super(props)
    				//初始化状态
    				this.state = { count: 0 }
    			}
    
    			//加1按钮的回调
    			add = () => {
    				//获取原状态
    				const { count } = this.state
    				//更新状态
    				this.setState({ count: count + 1 })
    			}
    
    			//卸载组件按钮的回调
    			death = () => {
    				ReactDOM.unmountComponentAtNode(document.getElementById('test'))
    			}
    
    			//强制更新按钮的回调
    			force = () => {
    				this.forceUpdate()
    			}
    
    			//若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
    			static getDerivedStateFromProps (props, state) {
    				console.log('12、21、31---getDerivedStateFromProps', props, state);
    				return null
    			}
    
    			//在更新之前获取快照('任何值都可以作为快照值')
    			getSnapshotBeforeUpdate () {
    				console.log('24、33---getSnapshotBeforeUpdate');
    				return 'atguigu'
    			}
    
    			//组件挂载完毕的钩子
    			componentDidMount () {
    				console.log('14---Count---componentDidMount');
    			}
    
    			//组件将要卸载的钩子
    			componentWillUnmount () {
    				console.log('41---Count---componentWillUnmount');
    			}
    
    			//控制组件更新的“阀门”
    			shouldComponentUpdate () {
    				console.log('22---Count---shouldComponentUpdate');
    				return true
    			}
    
    			//组件更新完毕的钩子(前一个Props,前一个State、前一个snapshotValue(快照值))
    			componentDidUpdate (preProps, preState, snapshotValue) {
    				console.log('25、34---Count---componentDidUpdate', preProps, preState, snapshotValue);
    			}
    
    			render () {
    				console.log('13、23、32---Count---render');
    				const { count } = this.state
    				return (
    					<div>
    						<h2>当前求和为:{count}</h2>
    						<button onClick={this.add}>点我+1</button>
    						<button onClick={this.death}>卸载组件</button>
    						<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
    					</div>
    				)
    			}
    		}
    
    		//渲染组件Count/A
    		ReactDOM.render(<Count count={199} />, document.getElementById('test'))
    		// ReactDOM.render(, document.getElementById('test'))
    		//渲染组件
    	script>
    body>
    
    html>
    
    6、react生命周期(新)图

    React_第2张图片

    7、getSnapshotBeforeUpdate
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>04_getSnapshotBeforeUpdate的使用场景title>
    	<style>
    		.list {
    			width: 200px;
    			height: 150px;
    			background-color: skyblue;
    			overflow: auto;
    		}
    
    		.news {
    			height: 30px;
    		}
    	style>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/17.0.1/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/babel.min.js">script>
    
    	<script type="text/babel">
    		class NewsList extends React.Component {
    
    			state = { newsArr: [] }
    
    			componentDidMount () {
    				setInterval(() => {
    					//获取原状态
    					const { newsArr } = this.state
    					//模拟一条新闻
    					const news = '新闻' + (newsArr.length + 1)
    					//更新状态
    					this.setState({ newsArr: [news, ...newsArr] })
    				}, 1000);
    			}
    
    			getSnapshotBeforeUpdate () {
    				return this.refs.list.scrollHeight
    			}
    
    			componentDidUpdate (preProps, preState, height) {
    				this.refs.list.scrollTop += this.refs.list.scrollHeight - height
    			}
    
    			render () {
    				return (
    					<div className="list" ref="list">
    						{
    							this.state.newsArr.map((n, index) => {
    								return <div key={index} className="news">{n}</div>
    							})
    						}
    					</div>
    				)
    			}
    		}
    		ReactDOM.render(<NewsList />, document.getElementById('test'))
    	script>
    body>
    
    html>
    

    十三、DOM的Diffing算法

    1、验证Diffing算法
    DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8">
    	<title>01_验证Diffing算法title>
    head>
    
    <body>
    	
    	<div id="test">div>
    
    	
    	<script type="text/javascript" src="../js/17.0.1/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/17.0.1/babel.min.js">script>
    
    	<script type="text/babel">
    		class Time extends React.Component {
    			state = { date: new Date() }
    
    			componentDidMount () {
    				setInterval(() => {
    					this.setState({
    						date: new Date()
    					})
    				}, 1000)
    			}
    
    			render () {
    				return (
    					<div>
    						<h1>hello</h1>
    						<input type="text" />
    						<span>现在是:{this.state.date.toTimeString()}<input type="text" /></span>
    					</div>
    				)
    			}
    		}
    
    		ReactDOM.render(<Time />, document.getElementById('test'))
    	script>
    body>
    
    html>
    
    2、key的作用
    DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8">
    	<title>02_key的作用title>
    head>
    
    <body>
    	<div id="test">div>
    	
    	<script type="text/javascript" src="../js/react.development.js">script>
    	
    	<script type="text/javascript" src="../js/react-dom.development.js">script>
    	
    	<script type="text/javascript" src="../js/babel.min.js">script>
    
    	<script type="text/babel">
    		/*
    		 经典面试题:
    				1). react/vue中的key有什么作用?(key的内部原理是什么?)
    				2). 为什么遍历列表时,key最好不要用index?
    			  
    				1. 虚拟DOM中key的作用:
    						1). 简单的说: key是虚拟DOM对象的标识, 在更新显示时key起着极其重要的作用。
    	
    						2). 详细的说: 当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】, 
    													随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:
    	
    										a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
    													(1).若虚拟DOM中内容没变, 直接使用之前的真实DOM
    													(2).若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
    	
    										b. 旧虚拟DOM中未找到与新虚拟DOM相同的key
    													根据数据创建新的真实DOM,随后渲染到到页面
    										
    				2. 用index作为key可能会引发的问题:
    									1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
    													会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
    	
    									2. 如果结构中还包含输入类的DOM:
    													会产生错误DOM更新 ==> 界面有问题。
    													
    									3. 注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,
    										仅用于渲染列表用于展示,使用index作为key是没有问题的。
    						
    				3. 开发中如何选择key?:
    									1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
    									2.如果确定只是简单的展示数据,用index也是可以的。
    		 */
    
    		/* 
    			慢动作回放----使用index索引值作为key
    	
    				初始数据:
    						{id:1,name:'小张',age:18},
    						{id:2,name:'小李',age:19},
    				初始的虚拟DOM:
    						
  • 小张---18
  • 小李---19
  • 更新后的数据: {id:3,name:'小王',age:20}, {id:1,name:'小张',age:18}, {id:2,name:'小李',age:19}, 更新数据后的虚拟DOM:
  • 小王---20
  • 小张---18
  • 小李---19
  • ----------------------------------------------------------------- 慢动作回放----使用id唯一标识作为key 初始数据: {id:1,name:'小张',age:18}, {id:2,name:'小李',age:19}, 初始的虚拟DOM:
  • 小张---18
  • 小李---19
  • 更新后的数据: {id:3,name:'小王',age:20}, {id:1,name:'小张',age:18}, {id:2,name:'小李',age:19}, 更新数据后的虚拟DOM:
  • 小王---20
  • 小张---18
  • 小李---19
  • */
    class Person extends React.Component { state = { persons: [ { id: 1, name: '小张', age: 18 }, { id: 2, name: '小李', age: 19 }, ] } add = () => { const { persons } = this.state const p = { id: persons.length + 1, name: '小王', age: 20 } this.setState({ persons: [p, ...persons] }) } render () { return ( <div> <h2>展示人员信息</h2> <button onClick={this.add}>添加一个小王</button> <h3>使用index(索引值)作为key</h3> <ul> { this.state.persons.map((personObj, index) => { return <li key={index}>{personObj.name}---{personObj.age}<input type="text" /></li> }) } </ul> <hr /> <hr /> <h3>使用id(数据的唯一标识)作为key</h3> <ul> { this.state.persons.map((personObj) => { return <li key={personObj.id}>{personObj.name}---{personObj.age}<input type="text" /></li> }) } </ul> </div> ) } } ReactDOM.render(<Person />, document.getElementById('test'))
    script> body> html>

    十四、复习

    1、类的基本知识
    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="UTF-8">
    	<title>1_类的基本知识title>
    head>
    
    <body>
    	<script type="text/javascript">
    		/* 
    			总结:
    				1.类中的构造器不是必须要写的,要对实例进行一些初始化的操作,如添加指定属性时才写。
    				2.如果A类继承了B类,且A类中写了构造器,那么A类构造器中的super是必须要调用的。
    				3.类中所定义的方法,都放在了类的原型对象上,供实例去使用。
    		*/
    		//创建一个Person类
    		class Person {
    			//构造器方法
    			constructor(name, age) {
    				//构造器中的this是谁?—— 类的实例对象
    				this.name = name
    				this.age = age
    			}
    			//一般方法
    			speak () {
    				//speak方法放在了哪里?——类的原型对象上,供实例使用
    				//通过Person实例调用speak时,speak中的this就是Person实例
    				console.log(`我叫${this.name},我年龄是${this.age}`);
    			}
    		}
    		const p = new Person('Jin', 18);
    		console.log(p);
    		p.speak();
    
    		//创建一个Student类,继承于Person类
    		class Student extends Person {
    			constructor(name, age, grade) {
    				super(name, age)
    				this.grade = grade
    				this.school = '尚硅谷'
    			}
    			//重写从父类继承过来的方法
    			speak () {
    				console.log(`我叫${this.name},我年龄是${this.age},我读的是${this.grade}年级`);
    				this.study()
    			}
    			study () {
    				//study方法放在了哪里?——类的原型对象上,供实例使用
    				//通过Student实例调用study时,study中的this就是Student实例
    				console.log('我很努力的学习');
    			}
    		}
    		const s = new Student('Jin', 18, '大一');
    		console.log(s);
    		s.speak();
    
    		class Car {
    			constructor(name, price) {
    				this.name = name
    				this.price = price
    				// this.wheel = 4
    			}
    			//类中可以直接写赋值语句,如下代码的含义是:给Car的实例对象添加一个属性,名为a,值为1
    			a = 1
    			wheel = 4
    			static demo = 100
    		}
    		const c1 = new Car('奔驰c63', 199)
    		console.log(c1);
    		console.log(Car.demo);
    	script>
    body>
    
    html>
    
    2、原生事件绑定
    DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8" />
    	<title>2_原生事件绑定title>
    head>
    
    <body>
    	<button id="btn1">按钮1button>
    	<button id="btn2">按钮2button>
    	<button onclick="demo()">按钮3button>
    
    	<script type="text/javascript">
    		const btn1 = document.getElementById('btn1')
    		btn1.addEventListener('click', () => {
    			alert('按钮1被点击了')
    		})
    
    		const btn2 = document.getElementById('btn2')
    		btn2.onclick = () => {
    			alert('按钮2被点击了')
    		}
    
    		function demo () {
    			alert('按钮3被点击了')
    		}
    
    	script>
    body>
    
    html>
    
    3、类方法中的this指向
    DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8" />
    	<title>3_类方法中的this指向title>
    head>
    
    <body>
    	<script type="text/javascript">
    		class Person {
    			constructor(name, age) {
    				this.name = name
    				this.age = age
    			}
    			study () {
    				//study方法放在了哪里?——类的原型对象上,供实例使用
    				//通过Person实例调用study时,study中的this就是Person实例
    				console.log(this);
    			}
    		}
    
    		const p1 = new Person('tom', 18)
    		p1.study() //通过实例调用study方法
    		const x = p1.study
    		x()
    
    	script>
    body>
    
    html>
    
    4、展开运算符
    DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8" />
    	<title>4_展开运算符title>
    head>
    
    <body>
    	<script type="text/javascript">
    		let arr1 = [1, 3, 5, 7, 9]
    		let arr2 = [2, 4, 6, 8, 10]
    		console.log(...arr1); //展开一个数组
    		let arr3 = [...arr1, ...arr2]//连接数组
    		console.log(arr3)
    
    		//在函数中使用
    		function sum (...numbers) {
    			return numbers.reduce((preValue, currentValue) => {
    				return preValue + currentValue
    			})
    		}
    		console.log(sum(1, 2, 3, 4));
    
    		//构造字面量对象时使用展开语法
    		let person = { name: 'tom', age: 18 }
    		let person2 = { ...person }
    		//console.log(...person); //报错,展开运算符不能展开对象
    		console.log(person2);
    		person.name = 'jerry'
    		console.log(person);
    
    		//合并
    		let person3 = { ...person, name: 'jack', address: "地球" }
    		console.log(person3);
    
    	script>
    body>
    
    html>
    
    5、对象相关的知识
    DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8" />
    	<title>5_对象相关的知识title>
    head>
    
    <body>
    	<script type="text/javascript">
    		let a = 'name'
    
    		let obj = {} // {name:'tom'}
    		obj[a] = 'tom'
    		console.log(obj);
    
    	script>
    body>
    
    html>
    
    6、演示函数的柯里化
    DOCTYPE html>
    <html>
    
    <head>
    	<meta charset="UTF-8" />
    	<title>6_演示函数的柯里化title>
    head>
    
    <body>
    	<script type="text/javascript">
    		/* function sum(a,b,c){
    			return a+b+c
    		} */
    
    		function sum (a) {
    			return (b) => {
    				return (c) => {
    					return a + b + c
    				}
    			}
    		}
    		const result = sum(1)(2)(3)
    		console.log(result);
    	script>
    body>
    
    html>
    

    二、react_staging

    一、01_react脚手架

    1、创建项目并启动
    #全局安装
    npm install -g create-react-app	或者
    npm install create-react-app -g
    #切换到想要创建项目的目录
    cd Desktop\Studying\React\源码\React
    #使用命令
    create-react-app hello-react
    #进入项文件夹
    cd hello-react
    #启动项目
    npm start 或者
    yarn start
    

    注:需要使用node.js的14版本以上的(之前使用的hi是12.18.1(本人使用的是NVM控制node.js版本号))

    React_第3张图片

    重新全局安装和创建项目

    React_第4张图片

    React_第5张图片

    成功显示

    React_第6张图片

    React_第7张图片

    2、脚手架自带文件

    public/index.html

    DOCTYPE html>
    <html lang="en">
    
    <head>
    	<meta charset="utf-8" />
    	
    	
    	<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    	
    	<meta name="viewport" content="width=device-width, initial-scale=1" />
    	
    	<meta name="theme-color" content="red" />
    	<meta name="description" content="Web site created using create-react-app" />
    	
    	<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    	
    	<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    	<title>React Apptitle>
    head>
    
    <body>
    	
    	<noscript>You need to enable JavaScript to run this app.noscript>
    	<div id="root">div>
    body>
    
    html>
    

    src/App.js

    import logo from './logo.svg';
    import './App.css';
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <p>
              Edit <code>src/App.js</code> and save to reload.
            </p>
            <a
              className="App-link"
              href="https://reactjs.org"
              target="_blank"
              rel="noopener noreferrer"
            >
              Learn React
            </a>
          </header>
        </div>
      );
    }
    
    export default App;
    

    src/index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import reportWebVitals from './reportWebVitals';
    
    ReactDOM.render(
    	// 可以检查自己写的是否符合ReactApi,然后给予提示
      <React.StrictMode>
        <App />
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    reportWebVitals();
    

    二、02_src_hello_react

    三、03_src_TodoList案例

    1.拆分组件、实现静态组件,注意:className、style的写法
    2.动态初始化列表,如何确定将数据放在哪个组件的state中?
                ——某个组件使用:放在其自身的state中
                ——某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升)
    3.关于父子之间通信:
            1.【父组件】给【子组件】传递数据:通过props传递
            2.【子组件】给【父组件】传递数据:通过props传递,要求父提前给子传递一个函数
    4.注意defaultChecked(只有在第一次执行起作用,在以后都不起作用) 和 checked的区别,类似的还有:defaultValue 和 value
    5.状态在哪里,操作状态的方法就在哪里
    

    四、04_src_配置代理

    # react脚手架配置代理总结
    # 方法一
    >package.json中追加如下配置
    ​```json
    "proxy":"http://localhost:5000"
    ​```
    说明:
    1. 优点:配置简单,前端请求资源时可以不加任何前缀。
    2. 缺点:不能配置多个代理。
    3. 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)
    # 方法二
    1. 第一步:创建代理配置文件
    

    在src下创建配置文件:src/setupProxy.js

    2. 编写setupProxy.js配置具体代理规则:
    const proxy = require('http-proxy-middleware')
    module.exports = function(app) {
      app.use(
        proxy('/api1', {  //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
          target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
          changeOrigin: true, //控制服务器接收到的请求头中host字段的值
          /*
          	changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
          	changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
          	changeOrigin默认值为false,但我们一般将changeOrigin值设为true
          */
          pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
        }),
        proxy('/api2', { 
          target: 'http://localhost:5001',
          changeOrigin: true,
          pathRewrite: {'^/api2': ''}
        })
      )
    }
    说明:
    1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
    2. 缺点:配置繁琐,前端请求资源时必须加前缀。
    

    五、05_src_github搜索案例_axios

    六、06_src_github搜索案例_pubsub

    七、07_src_github搜索案例_fetch

    # 1.xhr		fetch
    # 2.ajax	axios
    
    ## 二、github搜索案例相关知识点
    1.设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办。
    2.ES6小知识点:解构赋值+重命名
            let obj = {a:{b:1}}
            const {a} = obj; //传统解构赋值
            const {a:{b}} = obj; //连续解构赋值
            const {a:{b:value}} = obj; //连续解构赋值+重命名
    3.消息订阅与发布机制
            1.先订阅,再发布(理解:有一种隔空对话的感觉)
            2.适用于任意组件间通信
            3.要在组件的componentWillUnmount中取消订阅
    4.fetch发送请求(关注分离的设计思想)
            try {
                const response= await fetch(`/api1/search/users2?q=${keyWord}`)
                const data = await response.json()
                console.log(data);
            } catch (error) {
                console.log('请求出错',error);
            }
    

    八、08_src_路由的基本使用

    ## 三、路由的基本使用
    1.明确好界面中的导航区、展示区
    2.导航区的a标签改为Link标签
            <Link to="/xxxxx">Demo</Link>
    3.展示区写Route标签进行路径的匹配
            <Route path='/xxxx' component={Demo}/>
    4.<App>的最外侧包裹了一个<BrowserRouter><HashRouter>
                
    ## 十三、BrowserRouter与HashRouter的区别
    1.底层原理不一样:
            BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
            HashRouter使用的是URL的哈希值。
    2.path表现形式不一样
            BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
            HashRouter的路径包含#,例如:localhost:3000/#/demo/test
    3.刷新后对路由state参数的影响
            (1).BrowserRouter没有任何影响,因为state保存在history对象中。
            (2).HashRouter刷新后会导致路由state参数的丢失!!!
    4.备注:HashRouter可以用于解决一些路径错误相关的问题。
    

    九、09_src_NavLink的使用

    ## 四、路由组件与一般组件
    1.写法不同:
            一般组件:<Demo/>
            路由组件:<Route path="/demo" component={Demo}/>
    2.存放位置不同:
            一般组件:components
            路由组件:pages
    3.接收到的props不同:
            一般组件:写组件标签时传递了什么,就能收到什么
            路由组件:接收到三个固定的属性
                    history:
                                go: ƒ go(n)
                                goBack: ƒ goBack()
                                goForward: ƒ goForward()
                                push: ƒ push(path, state)
                                replace: ƒ replace(path, state)
                    location:
                                pathname: "/about"
                                search: ""
                                state: undefined
                    match:
                                params: {}
                                path: "/about"
                                url: "/about"
    

    十、10_src_封装NavLink

    ## 五、NavLink与封装NavLink
        1.NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
        2.标签体内容是一个特殊的标签属性
        3.通过this.props.children可以获取标签体内容
    

    十一、11_src_Switch的使用

    ## 六、Switch的使用
        1.通常情况下,path和component是一一对应的关系。
        2.Switch可以提高路由匹配效率(单一匹配)

    十二、12_src_解决样式丢失问题

    ## 七、解决多级路径刷新页面样式丢失的问题
        1.public/index.html 中 引入样式时不写 .// (常用)
        2.public/index.html 中 引入样式时不写 ./%PUBLIC_URL% (常用)
        3.使用HashRouter
    

    十三、13_src_精准匹配与模糊匹配

    ## 八、路由的严格匹配与模糊匹配
        1.默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
        2.开启严格匹配:<Route exact={true} path="/about" component={About}/>
        3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
    

    十四、14_src_Redirect的使用

    ## 九、Redirect的使用	
        1.一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
        2.具体编码:
                <Switch>
                    <Route path="/about" component={About}/>
                    <Route path="/home" component={Home}/>
                    <Redirect to="/about"/>
                </Switch>
    

    十五、15_src_嵌套路由的使用

    ## 十、嵌套路由
        1.注册子路由时要写上父路由的path值
        2.路由的匹配是按照注册路由的顺序进行的
    

    十六、16_src_向路由组件传递params参数

    十七、17_src_向路由组件传递search参数

    十八、18_src_向路由组件传递state参数

    ## 十一、向路由组件传递参数
    1.params参数
                路由链接(携带参数)<Link to='/demo/test/tom/18'}>详情</Link>
                注册路由(声明接收)<Route path="/demo/test/:name/:age" component={Test}/>
                接收参数:this.props.match.params
    2.search参数
                路由链接(携带参数)<Link to='/demo/test?name=tom&age=18'}>详情</Link>
                注册路由(无需声明,正常注册即可)<Route path="/demo/test" component={Test}/>
                接收参数:this.props.location.search
                备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
    3.state参数
                路由链接(携带参数)<Link to={{pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link>
                注册路由(无需声明,正常注册即可)<Route path="/demo/test" component={Test}/>
                接收参数:this.props.location.state
                备注:刷新也可以保留住参数
    

    十九、19_src_push与replace模式

    二十、20_src_编程式路由导航

    ## 十二、编程式路由导航
        借助this.prosp.history对象上的API对操作路由跳转、前进、后退
                -this.prosp.history.push()
                -this.prosp.history.replace()
                -this.prosp.history.goBack()
                -this.prosp.history.goForward()
                -this.prosp.history.go()
    

    二十一、21_src_withRouter的使用

    //withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
    //withRouter的返回值是一个新组件
    

    二十二、22_src_antd组件库的使用

    ## 十四、antd的按需引入+自定义主题
        1.安装依赖:yarn add react-app-rewired customize-cra babel-plugin-import less less-loader
        2.修改package.json
                ....
                    "scripts": {
                        "start": "react-app-rewired start",
                        "build": "react-app-rewired build",
                        "test": "react-app-rewired test",
                        "eject": "react-scripts eject"
                    },
                ....
        3.根目录下创建config-overrides.js
                //配置具体的修改规则
                const { override, fixBabelImports,addLessLoader} = require('customize-cra');
                module.exports = override(
                    fixBabelImports('import', {
                        libraryName: 'antd',
                        libraryDirectory: 'es',
                        style: true,
                    }),
                    addLessLoader({
                        lessOptions:{
                            javascriptEnabled: true,
                            modifyVars: { '@primary-color': 'green' },
                        }
                    }),
                );
            4.备注:不用在组件里亲自引入样式了,即:import 'antd/dist/antd.css'应该删掉
    

    三、redux_test

    一、1_src_纯react版

    1.英文文档: https://redux.js.org/
    2.中文文档: http://www.redux.org.cn/
    3.Github: https://github.com/reactjs/redux
    

    二、2_src_redux精简版

    ## 1.求和案例_redux精简版
    (1).去除Count组件自身的状态
    (2).src下建立:
            -redux
                -store.js
                -count_reducer.js
    
    (3).store.js:
        1).引入redux中的createStore函数,创建一个store
        2).createStore调用时要传入一个为其服务的reducer
        3).记得暴露store对象
    
    (4).count_reducer.js:
        1).reducer的本质是一个函数,接收:preState,action,返回加工后的状态
        2).reducer有两个作用:初始化状态,加工状态
        3).reducer被第一次调用时,是store自动触发的,
                        传递的preState是undefined,
                        传递的action是:{type:'@@REDUX/INIT_a.2.b.4}
    
    (5).在index.js中监测store中状态的改变,一旦发生改变重新渲染
    备注:redux只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。
    

    三、3_src_redux完整版

    ## 2.求和案例_redux完整版
        新增文件:
            1.count_action.js 专门用于创建action对象
            2.constant.js 放置容易写错的type值
    

    四、4_src_异步action版

    ## 3.求和案例_redux异步action版
     (1).明确:延迟的动作不想交给组件自身,想交给action
     (2).何时需要异步action:想要对状态进行操作,但是具体的数据靠异步任务返回。
     (3).具体编码:
                1).yarn add redux-thunk,并配置在store中
                2).创建action的函数不再返回一般对象,而是一个函数,该函数中写异步任务。
                3).异步任务有结果后,分发一个同步的action去真正操作数据。
     (4).备注:异步action不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步action。
    

    五、5_src_react-redux的基本使用

    ## 4.求和案例_react-redux基本使用
    (1).明确两个概念:
        1).UI组件:不能使用任何redux的api,只负责页面的呈现、交互等。
        2).容器组件:负责和redux通信,将结果交给UI组件。
    (2).如何创建一个容器组件————靠react-redux 的 connect函数
            connect(mapStateToProps,mapDispatchToProps)(UI组件)
                -mapStateToProps:映射状态,返回值是一个对象
                -mapDispatchToProps:映射操作状态的方法,返回值是一个对象
    (3).备注1:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入
    (4).备注2:mapDispatchToProps,也可以是一个对象
    

    六、6_src_react-redux优化

    ## 5.求和案例_react-redux优化
    (1).容器组件和UI组件整合一个文件
    (2).无需自己给容器组件传递store,给包裹一个即可。
    (3).使用了react-redux后也不用再自己检测redux中状态的改变了,容器组件可以自动完成这个工作。
    (4).mapDispatchToProps也可以简单的写成一个对象
    (5).一个组件要和redux“打交道”要经过哪几步?
        (1).定义好UI组件---不暴露
        (2).引入connect生成一个容器组件,并暴露,写法如下:
                connect(
                    state => ({key:value}), //映射状态
                    {key:xxxxxAction} //映射操作状态的方法
                )(UI组件)
        (4).在UI组件中通过this.props.xxxxxxx读取和操作状态
    

    七、7_src_react-redux_数据共享版

    ## 6.求和案例_react-redux数据共享版
    (1).定义一个Pserson组件,和Count组件通过redux共享数据。
    (2).为Person组件编写:reducer、action,配置constant常量。
    (3).重点:Person的reducer和Count的Reducer要使用combineReducers进行合并,
            合并后的总状态是一个对象!!!
    (4).交给store的是总reducer,最后注意在组件中取出状态的时候,记得“取到位”。
    

    八、8_src_react-redux_开发者工具

    ## 7.求和案例_react-redux开发者工具的使用
    (1).yarn add redux-devtools-extension
    (2).store中进行配置
            import {composeWithDevTools} from 'redux-devtools-extension'
            const store = createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))
    

    九、9_src_最终版

    ## 8.求和案例_react-redux最终版
    (1).所有变量名字要规范,尽量触发对象的简写形式。
    (2).reducers文件夹中,编写index.js专门用于汇总并暴露所有的reducer
    

    四、小提示

    #结构赋值
    const {value} = this.selectNumber
    #强制刷新页面(不走缓存)
    shift+刷新
    #安装插件ES7+ React/Redux/React-Native snippets
    rcc/rfc(插件快速编程)
    

    你可能感兴趣的:(前端,react.js,前端,前端框架)