初识react
从vue到react,可以发现这两种框架有很大的相似之处
1.相同之处
有着相似的语法,相似的生命周期,相似的父子组件传值、子父组件传值和非父子组件传值。
2.不同之处着实太多,在此不一一说明
着重介绍react框架的重点和核心点。
关于react的组件传值
父子组件传值 ||从父组件到子组件不仅可以传数据,还可以传事件
//父组件
import React, { Component } from "react";
//引入子组件
import ChildModule from "./components/ChildModule";
export class FacherModule extends Component {
//定义数据
state = {
data: [
{
id: 1,
name: "name1",
age: 18,
sex: 男,
}
],
};
//事件
dataOnClickFun = (e) => {
console.log(e.target);
};
render() {
return (
<div>
FacherModule
<ChildModule value={this.props.data} dataFun={this.dataOnClickFun}></ChildModule>
</div>
);
}
}
export default FacherModule;
//子组件
import React, { Component } from "react";
import "../App.css";
export class ChildModule extends Component {
constructor(props) {
super(props);
console.log(props);
}
render() {
return (
<div>
ChildModule
{this.props.value.map((value, index) => {
return (
<ul key={value.id} className="ulBox">
<li>{value.id}</li>
<li>{value.name}</li>
<li>{value.age}</li>
</ul>
);
})}
</div>
);
}
}
export default ChildModule;
子组件输出结果
![UG`KS[T{E_}I%WXZ7FL1_A.png 是个object类型的数据,父子组件传值已基本完成,注意: value可以传数组,对象,字符串等数据类型
1.子组件到父组件传值
//父组件代码
import React, { Component } from "react";
//引入子组件
import ChildModule from "./components/ChildModule";
export class FatcherModule extends Component {
//从子组件触发的事件,
changeFatherval = (value) => {
console.log(value);
};
render() {
return (
<div>
FatcherModule
//toFatcher 在父组件中要与子组件传递的名要一致
<ChildModule toFatcher={this.changeFatherval}></ChildModule>
</div>
);
}
}
export default FatcherModule;
//子组件
import React, { Component } from "react";
import "../App.css";
export class ChildModule extends Component {
constructor(props) {
super(props);
console.log(props);
}
//子组件触发的事件
ChildFun = () => {
console.log("111");
//toFatcher子组件传递的事件名称
this.props.toFatcher("从子组件传到父组件的数据");
};
render() {
return (
<div>
ChildModule
<button onClick={this.ChildFun}>子到父传值</button>
</div>
);
}
}
export default ChildModule;
2.无论是vue还是React,都有关于请求数据,发送求情这以行为,在此以axiox请求举例说明
在src文件下建utils文件夹,内有request.js文件。
//引入axios
import axios from 'axios'
import qs from 'qs'
//get delete post put
// 使用由库提供的配置的默认值来创建实例
var requests = axios.create()
// 覆写库的超时默认值
requests.defaults.timeout = 50000
//设置请求头
requests.defaults.baseURL = ''
// 添加请求拦截器
requests.interceptors.request.use(
function (config) {
//设置token 1.0
config.headers = {
...config.headers,
token名: 'token值',
}
//2.0
if (config.data && !(config.data instanceof FormData)) {
config.data = qs.stringify(config.data)
}
config.url && (config.url =`${config.url}token=1ec949a15fb709370f`)
// let tokenStr = localStorage.getItem('token')
return config
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error)
}
)
// 添加响应拦截器
requests.interceptors.response.use(
function (response) {
//请求到的数据进行脱壳处理
const {data}=response
return data
},
function (error) {
return Promise.reject(error)
}
)
//get请求方式
const get = (url, data) => {
return new Promise((res, rej) => {
requests
.get(url, { params: data })
.then(val => {
res(val)
})
.catch(err => {
rej(err)
})
})
}
//deleter请求方式
const deleter = (url, data) => {
return new Promise((res, rej) => {
requests
.delete(url, { params: data })
.then(val => {
res(val)
})
.catch(err => {
rej(err)
})
})
}
//post请求方式
const post = (url, data) => {
return new Promise((res, rej) => {
requests
.post(url, data)
.then(val => {
res(val)
})
.catch(err => {
rej(err)
})
})
}
//put请求方式
const put = (url, data) => {
return new Promise((res, rej) => {
requests
.put(url, data)
.then(success => {
res(success)
})
.catch(error => {
rej(error)
})
})
}
export { get, post, deleter,put }
注:请求封装和发送请求需要传递的token值的方式和请求到的数据进行脱壳处理,请求失败处理已经进行了分情况操作
引入:
//引入
import {post,get,put,deleter} from "./utils/request"
在生命周期里调用
//发送请求
//挂载之后
componentDidMount(){
post("接口地址").then(res=>{console.log(res)}).catch(err=>{console.log(err)})
}//可以获取到数据
3.既然涉及到了React的生命周期,接下来会分析各个生命周期 react有三个生命周期阶段
1.挂载过程
1.1 constructor()
constructor() 中完成了React数据的初始化,它接受两个参数:props和context,当想在函数内部使用这两个参数时,需使用super()传入这两个参数。
注意:只要使用了constructor()就必须写super(),否则会导致this指向错误。
1.2 componentWillMount()
componentWillMount()一般用的比较少,它更多的是在服务端渲染时使用。它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。
1.3 componentDidMount()
组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据使用setState进行数据修改之后组件会重新渲染
2.卸载过程
2.1.componentWillUnmount () 在此处完成组件的卸载和数据的销毁。
1.1 clear你在组建中所有的setTimeout,setInterval
1.2 移除所有组建中的监听 removeEventListener
1.3 有时候会碰到这个warning:
Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component.
解析:因为你在组件中的ajax请求返回setState,而你组件销毁的时候,请求还未完成,因此会报warning
解决方法:
componentDidMount() {
this.isMount === true
get().then(res => {
this.isMount && this.setState({ // 增加条件ismount为true时 当&&前面的条件为真时执行后面的操作
data:res
})
})
}
componentWillUnmount() {
this.isMount === false
}
3.更新过程
3.1 componentWillReceiveProps (nextProps)
- 在接受父组件改变后的props需要重新渲染组件时用到的比较多
- 接受一个参数nextProps
- 通过对比nextProps和this.props,将nextProps的state为当前组件的state,从而重新渲染组件
componentWillReceiveProps (nextProps) {
nextProps.openNotice !== this.props.openNotice&&this.setState({
openNotice:nextProps.openNotice
},() => {
console.log(this.state.openNotice:nextProps)
//将state更新为nextProps,在setState的第二个参数(回调)可以打 印出新的state
})
}
3.2 shouldComponentUpdate(nextProps,nextState)
- 主要用于性能优化(部分更新)
- 唯一用于控制组件重新渲染的生命周期,由于在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新
- 因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断
3.3 componentWillUpdate (nextProps,nextState)
shouldComponentUpdate返回true以后,组件进入重新渲染的流程,进入componentWillUpdate,这里同样可以拿到nextProps和nextState。
3.4 componentDidUpdate(prevProps,prevState)
组件更新完毕后,react只会在第一次初始化成功会进入componentDidmount,之后每次重新渲染后都会进入这个生命周期,这里可以拿到prevProps和prevState,即更新前的props和state。
3.5 render()
render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。
4. 新增的生命周期
4.1 getDerivedStateFromProps(nextProps, prevState)
代替componentWillReceiveProps()。老版本中的componentWillReceiveProps()方法判断前后两个 props 是否相同,如果不同再将新的 props 更新到相应的 state 上去。这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数。
4.2 getSnapshotBeforeUpdate(prevProps, prevState)
代替componentWillUpdate。
常见的 componentWillUpdate 的用例是在组件更新前,读取当前某个 DOM 元素的状态,并在 componentDidUpdate 中进行相应的处理。
这两者的区别在于:
4.2.1.
在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在
componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
4.2.2. getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。
此生命周期返回的任何值都将作为参数传递给componentDidUpdate()。