开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
前言
我本人的技术栈是Vue,工作上也一直大部分使用的都是Vue,期间断断续续有学过React,但是也止步于学了很久不用就忘了的阶段,作为一个有强烈求知欲望的前端(啊呸...还不是因为生活所迫!)要如何能摆脱掉这种困境呢?在网上看到很多大佬的学习方法之后,痛定思痛,决定采用主要以思维导图的方式来记录,由浅入深得再次去学习React,这一系列文章就围绕着这份思维导图来讲解。
React 基础
React组件分为函数组件和类组件,在v16.8之前,函数组件也被称为无状态组件,类组件被称为状态组件,直到v16.8发布,React Hooks的出现,算是打破了这一局面,函数组件也可以拥有自己的state了(利用useState)
JSX
在React中,使用JSX语法来实现用户界面,JSX就是一种语法糖,在经过Babel转译之后,其实就是JavaScript的一些API的调用。可以在花括号里写 JavaScript表达式;
let name = 'Rose'
function getName() {
return name;
}
const element = {name} // 获取变量
const element2 = {getName()} //获取函数返回值
State
通过state属性给组件设置自己的状态值,利用setState来进行合并修改,注意必须要通过setState来修改,不然视图不会更新。
export default class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 123
};
}
render() {
return (
<>
<h1>value:{this.state.value}</h1>
<h1>value1:{this.state.value1}</h1>
// 点击按钮之后value1为X,而value没有修改
<button onClick={() => this.setState({ value1: "X" })}>button</button>
</>
);
}
}
props
组件之间可以通过props传递数据,父组件向子组件传值,子组件通过props对象获取外部传递进来的数据
export default class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 123,
pname: "Jack"
};
}
render() {
return (
<>
<h1>value:{this.state.value}</h1>
<h1>value1:{this.state.value1}</h1>
{/* 点击按钮之后value1为X,而value没有修改 */}
<button onClick={() => this.setState({ value1: "X" })}>button</button>
<Child pname={this.state.pname}>
<span className="parent">我是父组件的DOM</span>
</Child>
</>
);
}
}
class Child extends React.Component {
render() {
return (
<div>
<div>我的父亲是:{this.props.pname}</div>
<div>接受到的父组件DOM:{this.props.children}</div>
</div>
)
}
}
生命周期
constructor
初始化state,对类组件的事件做一些处理,比如绑定this。
class Child2 extends React.Component {
constructor() {
super();
this.state = {
value: "hello",
this.handleClick = this.handleClick.bind(this);
};
}
handleClick() {
this.setState({
value: "goodbye"
})
}
render() {
return (
<div>
<button onClick={this.handleClick}>按钮</button>
</div>
)
}
}
getDerivedStateFromProps(nextProps,prevState)
getDerivedStateFromProps(nextProps,prevState)这个生命周期是一个静态方法,因此获取不到this。nextProps是父组件新传递的props,prevState为待合并的state。
只要组件更新就会执行,不管是props改变还是执行setState。这个方法虽然把props映射到了state上面,但是这个state在组件里面使用setState是无法修改的。
一般用于对props进行一些逻辑处理。
class Child extends React.Component {
constructor() {
super();
this.state = {
books: "",
age: "20"
};
}
static getDerivedStateFromProps(newProps) {
console.log("getDerivedStateFromProps");
const { pname } = newProps;
switch (pname) {
case "Jack":
return { books: "数学" };
}
}
ChangeProps = () => {
console.log("ChangeProps");
this.setState({
books: "语文"
});
};
ChangeAge = () => {
this.setState({
age: "18"
});
};
render() {
return (
<div>
<div>Jack给的书:{this.state.books}</div>
<button onClick={this.ChangeProps}>修改books</button>
<div>子组件age:{this.state.age}</div>
<button onClick={this.ChangeAge}>修改age</button>
<div>我的父亲是:{this.props.pname}</div>
<div>接受到的父组件DOM:{this.props.children}</div>
</div>
);
}
}
componentWillMount改为UNSAFE_componentWillMount
在v16.3中componentWillMount这个生命周期前面加上了UNSAFE_标识,根据源码得知,是由于render方法可以通过sholdUpdate来约束是否可以更新,但在render之前的生命周期却依然会被不必要的执行,所以官网不推荐再用这样的生命周期了。
componentWillReceiveProps改为UNSAFE_componentWillReceiveProps
只要父组件render函数执行,props被重新创建,子组件的componentWillReceiveProps方法就会被执行。
componentWillUpdate改为UNSAFE_componentWillUpdate
在这个生命周期中可以获取到组件在更新之前的状态,比如DOM。
render
获取到JSX创建的视图,一次 render 的过程,就是创建 React.element 元素的过程。 React.element就是React.creatElement()生成的对象。
getSnapshotBeforeUpdate,componentDidUpdate
该生命周期是为了获取更新前的快照,处于数据更新了但DOM还未更新的那个阶段。该生命周期主要与componentDidUpdate结合使用(如果使用getSnapshotBeforeUpdate,但不使用componentDidUpdate控制台会给出警告),该生命周期返回一个snapshot(快照),在componentDidUpdate中可通过第三个参数获取到该快照。
getSnapshotBeforeUpdate(prevProps,preState) {
return {
x:1
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(snapshot) // {x:1}
}
⚠注意: 如果在componentDidUpdate中使用setState,可能会误操作导致无限更新,所以在该生命周期中更新state要小心操作。写好条件限制。
componentDidMount
componentDidUpdate 在组件更新的时候执行,而componentDidMount则在组件DOM挂载的时候执行,可以在该生命周期中向后台发起请求,以及做一些DOM事件绑定之类的操作。
更新相关生命周期:
shouldComponentUpdate
shouldComponentUpdate(newProps,newState){
if (newProps.pname !== this.props.pname ) {
/* 渲染组件 */
return true
} else if(newState.page !== this.props.page ){
/* 渲染组件 */
return true
} else { /* 否则组件不渲染 */
return false
}
}
该生命周期在getDerivedStateFromProps之后在render之前执行,在getDerivedStateFromProps中props映射到的state将会合并到newState中,供shouldComponentUpdate使用。
组件销毁生命周期:
componentWillUnmount
看名字就可以得知该生命周期在组件销毁之前执行,可以在该生命周期中移除定时器,DOM的事件绑定等操作。
同样在函数组件中,现在也可以通过React Hooks实现函数组件的“生命周期”,在React Hooks的学习中再深究。
下一篇再继续学习React基础知识之Ref,context,css