React学习总结

1.React快速上手

1.1基础案例

<!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>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type='text/javascript' src='../js/react.development.js'></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type='text/javascript' src='../js/react-dom.development.js'></script>
<!-- 引入Babel,用于将es6转化为es5 用于将jsx转为js -->
<script type='text/javascript' src='../js/babel.min.js'></script>

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

1.2JSX语法规则

<!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>Document</title>
<style>
.title {
background-color: orange;
width: 200px;
}
</style>
</head>

<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type='text/javascript' src='../js/react.development.js'></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type='text/javascript' src='../js/react-dom.development.js'></script>
<!-- 引入Babel,用于将es6转化为es5 用于将jsx转为js -->
<script type='text/javascript' src='../js/babel.min.js'></script>

<script type="text/babel">
const myId = "xiaobaitiao";
const myData = "Hello,World"
const VDOM = (
<div>
<h2 id="{myId}" className="title">
<span style={{ color: 'white', fontSize: '30px' }}>{myData}</span>
</h2>
<h2>
<span>Hello,World</span>
</h2>
<input type="text"/>
</div>
)
ReactDOM.render(VDOM, document.getElementById('test'))
// jsx语法规则:
// 1.定于虚拟DOM时,不要写引号
// 2.标签中如果要混入JS表达式要用{}
// 3.样式的类名不要用class,要用className
// 4.内敛样式,要用style={{key:value}}的形式去写 如果value的值是一个变量不用加引号,如果是常量要加引号
// 5.只有一个根标签
// 6.标签必须是闭合的
// 7.标签首字母
// (1).若小写字母开头,则将该标签转为html同名元素,若html无该标签对应的同名元素,则报错
// (2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错

</script>



</body>

</html>

1.2.1JSX小练习

<!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>Document</title>
<style>
li {
list-style: none;
}
</style>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type='text/javascript' src='../js/react.development.js'></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type='text/javascript' src='../js/react-dom.development.js'></script>
<!-- 引入Babel,用于将es6转化为es5 用于将jsx转为js -->
<script type='text/javascript' src='../js/babel.min.js'></script>

<script type="text/babel">
const title = "前端JS框架列表";
const struct = ['Angular','React','Vue'];
// react 会自动遍历数组,但是不会遍历对象
// 此处一定要写babel
// 1.创建虚拟DOM
const VDOM = (
<div>
<h2>{title}</h2>
<ul>
{
struct.map((num,index) => {
return <li key={index}>{num}</li>
})
}
</ul>
</div>
)
// 此处一定不要写引号,因为不是字符串
// 2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'));
</script>
</body>
</html>

1.3函数式组件

<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type='text/javascript' src='../js/react.development.js'></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type='text/javascript' src='../js/react-dom.development.js'></script>
<!-- 引入Babel,用于将es6转化为es5 用于将jsx转为js -->
<script type='text/javascript' src='../js/babel.min.js'></script>

<script type="text/babel">
// 1.创建函数式组件
function MyComponent(){
return <h2>我是用函数定义的组件(适用于简单组件)</h2>
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
/*
执行ReactDOM.render后发生了什么?
1.React解析组件标签,找到了MyComponent组件
2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中
*/
</script>
</body>

1.4组件属性之state

1.4.1类式组件

<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type='text/javascript' src='../js/react.development.js'></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type='text/javascript' src='../js/react-dom.development.js'></script>
<!-- 引入Babel,用于将es6转化为es5 用于将jsx转为js -->
<script type='text/javascript' src='../js/babel.min.js'></script>

<script type="text/babel">
// 1.创建类式组件 一定要先继承React.Component
class MyComponent extends React.Component{
render() {
return <h2>我是用类定义的组件(适用于复杂组件的定义)</h2>
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'));
</script>
</body>

1.4.2初始化state

<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type='text/javascript' src='../js/react.development.js'></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type='text/javascript' src='../js/react-dom.development.js'></script>
<!-- 引入Babel,用于将es6转化为es5 用于将jsx转为js -->
<script type='text/javascript' src='../js/babel.min.js'></script>

<script type="text/babel">
// 1.创建类式组件 类名记得大写
class Weather extends React.Component {
constructor(props) {
super(props);
this.state = { isHot: false }
//解决changeWeather中this的指向问题
this.changeWeather = this.changeWeather.bind(this)
}
changeWeather() {
// changeWeather放在哪里? Weather的原型对象上,供实例适用
// 由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
// 类中的方法默认开启了局部的严格模式,所以changeWeather中的this是underfined
// 获取原来的isHot值
const isHot = this.state.isHot;
// 注意:状态必须通过setState进行修改 不能直接修改 例如:this.state.isHot = !this.state.isHot
this.setState({isHot:!isHot})
}
render() {
const { isHot } = this.state // 解构赋值
// 如果要绑定事件 onclick->onClick onblur->onBlur 大写
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h1>
}


}
// 2.渲染组件到页面
ReactDOM.render(<Weather />, document.getElementById('test'))

</script>
</body>

1.4.3state的简写形式

<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type='text/javascript' src='../js/react.development.js'></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type='text/javascript' src='../js/react-dom.development.js'></script>
<!-- 引入Babel,用于将es6转化为es5 用于将jsx转为js -->
<script type='text/javascript' src='../js/babel.min.js'></script>

<script type="text/babel">
// 1.创建类式组件 类名记得大写
class Weather extends React.Component {
// state 可以直接写在外面 初始化状态
state = {isHot:false,wind:'微风'}
// 自定义方法写成赋值语句加上箭头函数的形式,箭头函数本身并没有this,所以它向外延伸,找到this,也就是组件实例对象
changeWeather = ()=> {
const isHot = this.state.isHot;
this.setState({isHot:!isHot})
}
render() {
const { isHot } = this.state // 解构赋值
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h1>
}


}
// 2.渲染组件到页面
ReactDOM.render(<Weather />, document.getElementById('test'))

</script>
</body>

1.5组件属性之props

1.5.1props基本使用

<body>
<div id="test"></div>
<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(){
const {name,age,sex} = this.props

return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
<li>性别:{sex}</li>
</ul>
)
}
}
const p = {name:'小红',age:'22',sex:'女'}
//渲染组件到页面
ReactDOM.render(<Person name="小白" age="18" sex="男" />,document.getElementById('test'))
ReactDOM.render(<Person name="小黑" age="28" sex="男" />,document.getElementById('test1'))
ReactDOM.render(<Person name="小张" age="8" sex="男" />,document.getElementById('test2'))
//原生js不能用展开运算符展开对象,只能复制对象,但在babel和react的共同作用下,展开运算符可以展开对象
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))

</script>

</body>

1.5.2展开预算福复习

<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]//连接数组

//在函数中使用
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); //报错,展开运算符不能展开对象
person.name = 'jerry'
console.log(person2);
console.log(person);

//合并修改
let person3 = { ...person, name: 'jack', address: "地球" }
console.log(person3);
</script>
</body>

1.5.3对props进行限制

<body>
<div id="test"></div>
<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>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type='text/javascript' src='../js/prop-types.js'></script>
<script type='text/babel'>
// 创建组件
class Person extends React.Component {
render(){
const {name,age,sex} = this.props

return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age+1}</li>
<li>性别:{sex}</li>
</ul>
)
}

}
//对标签属性进行类型,必要性的限制
Person.propTypes = {
name:PropTypes.string.isRequired, //限制name必传,且为字符串
sex:PropTypes.string,//限制sex为字符串
age:PropTypes.number,//限制age为数值
speak:PropTypes.func,//限制speak为函数
}
//指定默认标签属性值
Person.defaultProps = {
sex:'不男不女',
age:18
}
const p = {name:'小红',age:22,sex:'女'}
//渲染组件到页面
ReactDOM.render(<Person name="小白" sex="男" />,document.getElementById('test'))
ReactDOM.render(<Person name="小黑" age="28" sex="男" />,document.getElementById('test1'))
ReactDOM.render(<Person name="小张" age="8" sex="男" />,document.getElementById('test2'))
//原生js不能用展开运算符展开对象,只能复制对象,但在babel和react的共同作用下,展开运算符可以展开对象
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))

</script>

</body>

1.5.4props简写形式

<body>
<div id="test"></div>
<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>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type='text/javascript' src='../js/prop-types.js'></script>
<script type='text/babel'>
// 创建组件
class Person extends React.Component {
//对标签属性进行类型,必要性的限制
static propTypes = {
name: PropTypes.string.isRequired, //限制name必传,且为字符串
sex: PropTypes.string,//限制sex为字符串
age: PropTypes.number,//限制age为数值
speak: PropTypes.func,//限制speak为函数
}
//指定默认标签属性值
static defaultProps = {
sex: '不男不女',
age: 18
}
render() {
const { name, age, sex } = this.props

return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age + 1}</li>
<li>性别:{sex}</li>
</ul>
)
}

}

const p = { name: '小红', age: 22, sex: '女' }
//渲染组件到页面
ReactDOM.render(<Person name="小白" sex="男" />, document.getElementById('test'))
ReactDOM.render(<Person name="小黑" age="28" sex="男" />, document.getElementById('test1'))
ReactDOM.render(<Person name="小张" age="8" sex="男" />, document.getElementById('test2'))
//原生js不能用展开运算符展开对象,只能复制对象,但在babel和react的共同作用下,展开运算符可以展开对象
ReactDOM.render(<Person {...p} />, document.getElementById('test3'))

</script>

</body>

1.6组件属性之refs

1.6.1字符串形式的ref

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">
//创建组件
class Demo extends React.Component {
//展示左侧输入框的数据
showData = () => {
const { input1 } = this.refs
// const {a,b} = this.props;
// alert(a+b)
alert(input1.value)
}
//展示右侧输入框的数据
showData2 = () => {
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 a="1" b="2" />, document.getElementById('test'))
</script>
</body>

1.6.2回调函数形式

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<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 = () => {
alert(this.input2.value)
}

render() {
return (
<div>
<input ref={(currentNode) => {
this.input1 = currentNode
}} type="text" placeholder="点击按钮提示数据" />&nbsp;
<button onClick={this.showData}>点我提示左侧的数据</button>
&nbsp;
<input ref={(currentNode) => {
this.input2 = currentNode
}} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}

//渲染组件到页面
ReactDOM.render(<Demo a="1" b="2" />, document.getElementById('test'))
</script>
</body>

1.6.3createRef的使用

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<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>

1.6.4react事件处理

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<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>

1.7react收集表单数据

1.7.1非受控组件

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">
//创建组件
class Login extends React.Component {
handleSubmit = (event) => {
event.preventDefault() //阻止表单提交
console.log(this);
const { username, password } = this
alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
}

render() {
return (
<form 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>

1.7.2受控组件

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>

<script type="text/babel">
//创建组件
class Login extends React.Component {

//初始化状态
state = {
username: '', //用户名
password: '' //密码
}

//保存用户名到状态中
saveUsername = (event) => {
this.setState({ username: event.target.value })
}

//保存密码到状态中
savePassword = (event) => {
this.setState({ password: event.target.value })
}

//表单提交的回调
handleSubmit = (event) => {
event.preventDefault() //阻止表单提交
const { username, password } = this.state
alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
}

render() {
return (
<form 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>

1.8react之生命周期

1.8.1生命周期函数(旧版)

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<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('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()
}

//组件将要挂载的钩子
componentWillMount() {
console.log('Count---componentWillMount');
}

//组件挂载完毕的钩子
componentDidMount() {
console.log('Count---componentDidMount');
}

//组件将要卸载的钩子
componentWillUnmount() {
console.log('Count---componentWillUnmount');
}

//控制组件更新的“阀门”
shouldComponentUpdate() {
console.log('Count---shouldComponentUpdate');
return true
}

//组件将要更新的钩子
componentWillUpdate() {
console.log('Count---componentWillUpdate');
}

//组件更新完毕的钩子
componentDidUpdate() {
console.log('Count---componentDidUpdate');
}

render() {
console.log('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('B---componentWillReceiveProps', props);
}

//控制组件更新的“阀门”
shouldComponentUpdate() {
console.log('B---shouldComponentUpdate');
return true
}

//组件将要更新的钩子
componentWillUpdate() {
console.log('B---componentWillUpdate');
}

//组件更新完毕的钩子
componentDidUpdate() {
console.log('B---componentDidUpdate');
}

render() {
console.log('B---render');
return (
<div>我是B组件,接收到的车是:{this.props.carName}</div>
)
}
}

//渲染组件
ReactDOM.render(<Count />, document.getElementById('test'))
</script>
</body>

1.8.2getSnapShotBeforeUpdate的使用场景

<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>

<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/17.0.1/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<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>