React基础
react的语法是jsx,下面是jsx语法规范
State
函数组件没有state
类组件第一种写法
class Home extends React.Component{
constructer(props){
super(props)
this.state = {
name: '王狗剩'
}
}
}
类组件语法糖
// 可以不写constructer、super
class Home extends React.Component{
state = {
name: '王狗剩'
}
}
点击事件修改state中的属性
不可以使用this.state.属性名直接修改,必须使用setState({ })的方式来修改
class Home extends React.Component{
state = {
name: '王狗剩'
}
render(){
return (
<div onClick={this.changeState}>点击修改state</div>
)
}
changeState = () => {
this.setState({
name: '李翠花'
})
}
}
Props
类组件
props依赖下载: 主要用于定义传值的数据类型默认数据
//npm
npm install --save prop-types
//Importing
import PropTypes from 'prop-types'; // ES6
// 所有类型如下
// optionalArray: PropTypes.array,
// optionalBool: PropTypes.bool,
// optionalFunc: PropTypes.func,
// optionalNumber: PropTypes.number,
// optionalObject: PropTypes.object,
// optionalString: PropTypes.string,
// optionalSymbol: PropTypes.symbol,
// 定义props的类型,必要性
Home.propsTypes = {
name: PropTypes.string.Required // after and type 默认必填
}
// 定义props的默认值
Home.defaultProps = {
name: 'default', // 如果不填的话name的默认值,和Required冲突
}
常用的写法
class Home extends React.Component {
// static 静态
static propsTypes = {
name: PropTypes.string.Required // after and type 默认必填
}
static defaultProps = {
name: 'default', // 如果不填的话name的默认值,和Required冲突
};
render() {}
}
函数式组件
function Home(props){ // 传值
return (
<div>{props.name}</div>
)
}
// 定义props的类型,必要性
Home.propsTypes = {
name: PropTypes.string.Required // after and type 默认必填
}
// 定义props的默认值
Home.defaultProps = {
name: 'default', // 如果不填的话name的默认值,和Required冲突
}
ref
// 已弃用
class Home extends React.Component {
render() {
return (
<div>
<button onClick={this.handler}>点击按钮</button>
<div ref="box1">{this.props.name}</div>
</div>
);
}
handler= () => {
console.log(this.refs.box1);
};
}
目前新版本使用回调的refs
// 如果 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,
// 所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
class Home extends React.Component {
render() {
return (
<div>
<button onClick={this.handler}>点击按钮</button>
<div ref={c=>{this.box = c}>{this.props.name}</div>
</div>
);
}
handler= () => {
console.log(this.box);
};
}
// 这样写就行了
class Home extends React.Component {
saveBox = (c) => {
this.box = c
}
render() {
return (
<div>
<button onClick={this.handler}>点击按钮</button>
<div ref={this.saveBox}>{this.props.name}</div>
</div>
);
}
handler= () => {
console.log(this.box);
};
}
// 官方最推荐的ref方式
class Home extends React.Component {
myRef = React.createRef()
render() {
return (
<div>
<button onClick={this.handler}>点击按钮</button>
<div ref={this.myRef}>{this.props.name}</div>
</div>
);
}
handler= () => {
console.log(this.myRef.current);
};
}
受控组件与非受控组件
// 例如在表单中输入时将数据管理的状态中的组件叫受控组件
// 在表单点击提交直接通过ref拿到数据并提交的组件叫非受控组件
在受控组件中使用函数柯里化
class Home extends React.Component {
state = {
username: '',
password: '',
};
render() {
return (
<div>
<form action="#">
<input onChange={this.saveFormData('username')} type="text" />
<input onChange={this.saveFormData('password')} type="password" />
</form>
</div>
);
}
saveFormData = (dataType) => { // 通过函数调用继续返回函数的方式,实现多次接受参数统一处理的函数编码形式叫函数柯里化
return (e) => {
// console.log(e.target.value);
// console.log(dataType);
this.setState({
[dataType]: e.target.value,
});
};
};
}
在受控组件中不使用函数柯里化
class Home extends React.Component {
state = {
username: '',
password: '',
};
render() {
return (
<div>
<form action="#">
<input onChange={(event) => { this.saveFormData('username', event.target.value);}} type="text" />
<input onChange={(event) => {this.saveFormData('password', event.target.value);}} type="password" />
</form>
</div>
);
}
}
React生命周期(旧)
第一阶段,初始化阶段,由ReactDOM.render()触发,初次渲染
constructor(){} =====> 构造器
componentWillMount(){} =======> 组件挂载之前
render(){} ======> 挂载结构
componentDidMount(){} =======> 组件挂载后
>>>>>>>常用钩子,一般用来做一些初始化的事情:开启定时器,发送网络请求,订阅消息
第二阶段,更新阶段,由内部this.setState()或父组件render()触发
shouldComponentUpdate() { =======> 组件是否被更新
return false;
}
componentWillUpdate(){} =======> 组件更新前
render(){} ======> 挂载结构
componentDidUpdate(){} =======> 组件更新后
第三阶段,卸载阶段,由ReactDOM.unmountComponentAtNode()触发
componentWillUnmount(){} =======> 组件卸载之前
>>>>>>>常用钩子,一般用来做一些收尾事情:关闭定时器,取消订阅消息
所有阶段展示
更新条件
1.setState() // 修改数据时触发更新
2.forceUpdate() // 强制更新,不经过shouldComponentUpdate(){}
3.componentWillReceiveProps(){} // 父组件更新引发更新
constructor(){} =====> 构造器
componentWillMount(){} =======> 组件挂载之前
render(){} ======> 挂载结构
componentDidMount(){} =======> 组件挂载后
componentWillUnmount(){} =======> 组件卸载之前
shouldComponentUpdate() { return false } =======> 组件是否被更新
componentWillUpdate(){} =======> 组件更新前
componentDidUpdate(){} =======> 组件更新后
React生命周期(新)
第一阶段,初始化阶段,由ReactDOM.render()触发,初次渲染
constructor(){} =====> 构造器
getDerivedStateFromProps() {} =====> 从Props获取派生
render(){} ======> 挂载结构
componentDidMount(){} =======> 组件挂载后
第二阶段:更新阶段,由内部this.setState()或父组件render()触发
getDerivedStateFromProps() {} =====> 从Props获取派生
shouldComponentUpdate() { return false } =======> 组件是否被更新
render(){} ======> 挂载结构
getSnapshotBeforeUpdate(prevProps, prevState) {} ======> // 获取快照更新前
componentDidUpdate(){} =======> 组件更新后
第三阶段:卸载阶段,由ReactDOM.unmountComponentAtNode()触发
componentWillUnmount(){} =======> 组件卸载之前
总结:
废弃了三个will
UNSAFE_componentWillMount() {} =====> 挂载前
UNSAFE_componentWillUpdate() {} =====> 更新前
UNSAFE_shouldComponentUpdate() { return false } =======> 组件是否被更新
新增了两个get
getDerivedStateFromProps(props, state) {} // 从Props获取派生
此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props。例如,实现 组件可能很方便,该组件会比较当前组件与下一组件,以决定针对哪些组件进行转场动画。
派生状态会导致代码冗余,并使组件难以维护。 确保你已熟悉这些简单的替代方案:
getSnapshotBeforeUpdate(prevProps, prevState) { // 获取快照更新前
return '123' // 这个值将返回给componentDidMount(){} 钩子函数的第三个参数,第一个:先前的props,第二个:先前的state,第三个:return的值
}
// 可用于固定滚动条的位置,
详情请看官网:
点击跳转官网,查看新增生命周期详情