1.propTypes
2.defaultProps
3.state、prop、render
当组件的state或者props发生改变的时候,render函数就会重新执行。
当父组件的render函数被运行时,它的子组件的render都将被重新运行一次。
4.虚拟DOM
React代码中render下的JSX内容:JSX —> React.createElement —> 虚拟DOM(JS对象)—> 真实的DOM
//JSX语法
render() {
return(
<div>item</div>
)
}
//JSX底层实现是通过createElement转换成虚拟DOM的
//createElement语法,也可以实现渲染页面,但这种写法没有JSX简便
render() {
return(
React.createElement('div', {}, 'item')
)
}
(1)第一种方案
1.准备state 数据
2.生成JSX 模板
3.数据 + 模板 结合,生成真是的DOM,来显示
4.state 发生改变
5.数据 + 模板 结合,生成真实的DOM,替换原始的DOM
缺陷:第一次生成一个完整DOM片段;第二次生成一个完整DOM片段;第二次的DOM替换第一次DOM,非常耗性能。
(2)第二种方案
1.state 数据
2.JSX 模板
3.数据 + 模板 结合,生成真是的DOM,来显示
4.state 发生改变
5.数据 + 模板 结合,生成真实的DOM,并不直接替换原始的DOM
6.新的DOM(DocumentFragment---文档碎片,js底层的,存在于内存中)和原始的DOM 作比对,找差异。
7.(假设找出input框发生了变化)
8.只用新的DOM中的有变化的元素(input元素),替换掉老的DOM中的旧元素(input元素)
缺陷:性能提升并不明显(对比也消耗性能)
(3)第三种方案---虚拟DOM
1.state 数据
2.JSX 模板
3.数据 + 模板 结合,生成虚拟DOM(虚拟DOM就是一个js对象,用它来描述真实DOM)(1.节点标签;2.节点属性;3.节点的子节点 / 内容)
['div', {id: 'abc'}, ['span', {}, 'hello world']]
4.用虚拟DOM的结构生成真是的DOM,来显示
<div id='abc'><span>hello world</span></div>
5.state发生变化
6.数据 + 模板 生成新的虚拟DOM(损耗:生成真实DOM > 虚拟DOM)
['div', {id: 'abc'}, ['span', {}, 'bye bye']]
7.比较原始虚拟DOM 和 新的虚拟DOM的区别(采用DIff算法),找到区别是span中的内容
8.直接操作DOM,改变span中的内容。
原因:在js中操作js对象(生成虚拟DOM,比较虚拟DOM)所耗性能 远小于 操作真实的DOM。
优点:
(1)性能提升来了;
(2)它使得跨端应用得以实现。React Native。
原生应用中不支持DOM,但支持虚拟DOM,可以把虚拟DOM转化成原生应用中的组件。
5.Diff算法(Different):同层比对(算法简单,速度快)
在jsx中做循环时(比如map循环返回新数组、子组件时),对循环中的每一项(最外层的)都要赋予一个唯一的、稳定的key值。有利于虚拟DOM比较过程,key值是Diff算法中的一部分。
不要用index作为key值,因为index有可能会改变,不稳定(比如删除数组中的一个元素时)。
6.React中ref(reference)的使用:在react中直接获取DOM元素。(尽量不用)
如果想要在setState更新完,再获取DOM时,需要注意setState是异步执行的(2)。
7.setState的异步执行
(1)当在短时间内,连续多次调用setState变更数据时,react将几次setState调用合并为一次,只进行一次数据更新、虚拟DOM对比、页面渲染。
(2)setState不会立即执行,setState的第二个参数也是一个函数,该函数表示为当setState执行完后再执行的函数,需要保证在setState后执行的内容,放在该函数体内。
8.生命周期
见本地“红点工厂”
使用场景:
(1)合理使用shouldComponentUpdate();
shouldComponentUpdate(nextProps, nextState){
if(nextProps.content !== this.props.content){
return true;
}else{
return false;
}
}
(2)Ajax异步请求放在componentDidMount()中;利用axios扩展工具进行ajax请求的发送。
使用前先进行安装axios,命令:npm install axios
import axios from 'axios';
//使用Charles进行接口数据模拟
//向地址/api/todolist,发送ajax请求,显示在list中
componentDidMount() {
axios.get('/api/todolist').then((res) => { //数据请求成功后
this.setState(()=>{
return {
list: [...res.data]
}
})
}).catch(() => { //数据请求失败后
alert('error')
})
}
ajax请求的是服务端的数据,在没有服务端数据时,可以在本地使用Charles进行接口数据模拟。
9.React的CSS动画(可以实现简单的动画,但有局限)(简单了解)
(1)App.js
import React, {Component, Fragment} from "react";
import AppStyle from './AppStyle.css';
class App extends Component {
constructor(props){
super(props)
this.state={
show: true
}
this.handleToggle=this.handleToggle.bind(this)
}
render() {
return (
<Fragment>
<div className={this.state.show ? 'show' : 'hide'}>hello</div>
<button onClick={this.handleToggle}>toggle</button>
</Fragment>
)
}
handleToggle(){
this.setState(()=>{
return{
show: this.state.show ? false : true
}
})
}
}
export default App;
(2.1)AppStyle.css(过渡动画)
.show{
opacity: 1;
transition: all 1s ease-in;
}
.hide{
opacity: 0;
transition: all 1s ease-in;
}
(2.2)AppStyle.css(动画效果)
.show{
animation: show-item 2s ease-in forwards;
}
.hide{
animation: hide-item 2s ease-in forwards;
}
@keyframes show-item {
0% {
opacity: 0;
color: blue;
}
50% {
opacity: 0.5;
color: green;
}
100% {
opacity: 1;
color: red;
}
}
@keyframes hide-item {
0% {
opacity: 1;
color: red;
}
50% {
opacity: 0.5;
color: green;
}
100% {
opacity: 0;
color: blue;
}
}
10.使用react-transition-group实现动画(可实现更复杂的)
文档位置:GitHub(https://github.com/reactjs/react-transition-group)> 进入Main documentation > 进入Components中的CSSTransition或其他组件
实例如下所示:
(1)App.js
import React, {Component, Fragment} from "react";
import { CSSTransition } from 'react-transition-group'; //动画组件
import AppStyle from './AppStyle.css';
class App extends Component {
constructor(props){
super(props)
this.state={
show: true
}
this.handleToggle=this.handleToggle.bind(this)
}
render() {
return (
<Fragment>
<CSSTransition in={this.state.show}
timeout={1000}
classNames="fade"
unmountOnExit
onEnter={(el) => {el.style.color='blue'}}
appear={true}>
<div>hello</div>
</CSSTransition>
<button onClick={this.handleToggle}>toggle</button>
</Fragment>
)
}
handleToggle(){
this.setState(()=>{
return{
show: this.state.show ? false : true
}
})
}
}
export default App;
(2)AppStyle.css
.fade-enter,fade-appear{
opacity: 0;
}
.fade-enter-active,fade-appear-active{
opacity: 1;
transition: opacity 1s ease-in;
}
.fade-enter-done,fade-appear-done{
opacity: 1;
}
.fade-exit{
opacity: 1;
}
.fade-exit-active{
opacity: 0;
transition: opacity 1s ease-in;
}
.fade-exit-done{
opacity: 0;
}