1、使用 PropTypes 类型检查
-
PropTypes 提供一系列验证器,可用于确保组件接收到的数据类型是有效的。当传入的 prop 值类型不正确时,JavaScript 控制台将会显示警告。出于性能方面的考虑,propTypes 仅在开发模式下进行检查。
-
通过配置特定的 defaultProps 属性来定义 props 的默认值。
-
npm install --save prop-types
import React,{Component} from 'react';
import PropTypes from 'prop-types';
class TodoItem extends Component {
constructor(props) {
super(props);
this.handClick = this.handClick.bind(this);
}
render(){
const {content,test} = this.props;
return (<li onClick={this.handClick}>{test}-{content }</li>)
}
handClick(){
const {itemDelete,index} = this.props;
itemDelete(index);
}
}
TodoItem.propTypes = {
test: PropTypes.string.isRequired,
content: PropTypes.string,
itemDelete: PropTypes.func,
index: PropTypes.number,
}
TodoItem.defaultProps = {
test: 'stranger'
}
export default TodoItem;
2、props,state,render之间的关系
- 当组件的 state 与 props 发生变化的时候, render函数就会重新执行
- 当父组件的 render 函数被运行时, 它的子组件的 render 函数也会被重新运行
父组件demo:
import React,{Component,Fragment} from 'react';
import Test from './Test';
class TodoList extends Component{
constructor(props) {
super(props);
this.state = {
inputValue: '',
}
}
render(){
// 当组件的 state 与 props 发生变化的时候, render函数就会重新执行.
const {inputValue} = this.state;
console.log("render");
return (
<Fragment>
<Test content={inputValue}/>
</Fragment>
);
}
export default TodoList;
子组件demo:
import React,{Component} from 'react';
class Test extends Component {
render(){
// 当父组件的 render 函数被运行时, 它的子组件的 render 函数也会被重新运行.
console.log("Test Render");
return <div>{this.props.content}</div>
}
}
export default Test;
3、虚拟DOM的Diff算法
React 中虚拟dom(js对象) 的 diff 算法:
- diff算法: 找原始虚拟dom 和新的虚拟dom直接的差异。
- 数据发生改变的时候才会产生diff 算法。(state 或者 props 发生改变的时候,也就是 调用 SetState()的时候。)
- 虚拟dom同级比对,发现某一层dom 不对的话,其他的就不比对了,就会把这层以下的所有的dom全部替换为新的虚拟dom。
- 虚拟dom在循环的时候能不用index做key值就尽量不用。
4、ref的使用
- ref可以帮助我们获取DOM元素:<input ref={(input) => { this.input = input }} />调用的时候就直接写this.input
- setState是异步函数,会晚一点执行,或者整合执行,总之不会立即执行,setState( () =({}), () ={} )
第一个参数是设置新的state,第二个参数是setState完成后的回调函数,如果想获取state更新后的dom节点,就必须写在回调函数里,有个先后顺序。
this.ol.querySelectorAll(‘div’).length获取ol里div的长度(个数)
import React,{Component,Fragment} from 'react';
import TodoItem from './TodoItem';
import './style.css';
class TodoList extends Component{
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: [],
}
this.handleChange = this.handleChange.bind(this);
this.handBtnClick = this.handBtnClick.bind(this);
this.handItemDelete = this.handItemDelete.bind(this);
}
render(){
// 当组件的 state 与 props 发生变化的时候, render函数就会重新执行.
const {inputValue} = this.state;
return (
<Fragment>
<div>
<label htmlFor="inputAra">输入内容</label>
<input className="input" id ="inputAra"
value={this.state.inputValue}
onChange={this.handleChange}
ref={(input)=>{this.input = input}}
/>
<button onClick={this.handBtnClick}>提交</button>
</div>
<ul ref={(ul)=>{this.ul= ul}}>
<div>
{this.getTodoItem()}
</div>
</ul>
</Fragment>
);
}
handleChange(e) {
// 函数,异步,性能提升
const value = this.input.value;
// const value = e.target.value;
this.setState(() => ({
inputValue:value,
}));
}
handBtnClick() {
this.setState((prevState) => ({
list: [...prevState.list,prevState.inputValue],
inputValue: '',
}),()=>{
console.log(this.ul.querySelectorAll('li').length);
});
// console.log(this.ul.querySelectorAll('li').length);
}
export default TodoList;
5、生命周期
**组件生命周期函数是指在某一时刻自动会被执行的函数
官网-生命周期
// 组件被挂载之前执行
componentWillMount(){
console.log("componentWillMount");
}
render(){
// 当组件的 state 与 props 发生变化的时候, render函数就会重新执行.
console.log("render");
return ();
}
// 组件被更新之前,自动执行
shouldComponentUpdate(){
console.log("shouldComponentUpdate");
return true;
}
// 组件被更新之前,自动执行,但是前提是shouldComponentUpdate返回true时才会执行
componentWillUpdate(){
console.log("componentWillUpdate");
return true;
}
// 组件更新完之后,自动执行
componentDidUpdate(){
console.log("componentDidUpdate");
}
// 组件被挂载在页面之后,自动执行
componentDidMount(){
console.log("componentDidMount");
}
// 一个组件要从父组件接收参数
// 只要父组件的render函数被重新执行了,子组件这个生命周期函数就会执行
componentWillReceiveProps(){
console.log("child componentWillReceiveProps");
}
// 组件被卸载时执行
componentWillUnmount(){
console.log("child componentWillUnmount");
}
- 所有的生命周期函数都可以不存在,但是render函数必须存在;因为react中的组件继承了Component组建的属性,这个组件中内置了其它生命周期函数,没有内置render函数的默认实现。
- 性能优化:父组件数据发生变化时,子组件也会刷新,但是很多时候的刷新是不必要的,可以在子组件生命周期函数中加以判断,只有特定条件下子组件才更新。
// 子组件性能优化使用
shouldComponentUpdate(nextProps,nextState){
if (nextProps.content!== this.props.content){
return true;
} else {
return false;
}
}
- 利用生命周期函数做axios请求,yarn add axios, 然后import axios from 'axios’即可使用。
componentDidMount(){
axios.get('/api/todolist')
.then(()=>{alert("success")})
.catch(()=>{alert("error")})
}
6、Charles来模拟后端数据
- 数据的mock就是数据的模拟
// npm install axios
import axios from 'axios'
componentDidMount() {
axios.get('./api/todolist')
.then((res) =({
this.setState(() =( ({
list: [...res.data]
}))
})
.catch(() =({console.log("erro")})
}