目录
react的生命周期(旧)
挂载时:
<script type="text/babel">
class Count extends React.Component{
// 构造器
constructor(props){
console.log('Count---constructor');
super(props)
// 初始化状态
this.state = {count: 0}
}
add = ()=>{
// 获取原状态
const {count} = this.state
// 更新状态
this.setState({count: count + 1})
}
// 组件将要挂载的钩子
componentWillMount(){
console.log('Count---componentWillMount');
}
// 组件将要挂载的钩子
componentDidMount(){
console.log('Count---componentDidMount');
}
// 组件将要被卸载
componentWillUnmount(){
console.log('Count---componentWillUnmount');
}
render(){
console.log('Count---render');
const {count} = this.state
return(
<div>
<h2>当前求和为:{count}</h2>
<button onClick={this.add}>+1</button>
</div>
)
}
}
// 渲染组件
ReactDOM.render(<Count />,document.getElementById('test'))
更新时:三条线
1. setState → shouldComponentUpdate(控制更新开关) → componentWillUpdate(将要进行更新) → render(更新) → componentDidUpdate(更新完毕)→ componentWillUnmount
在更新的时候,shouldComponentUpdate会判断是否应该执行更新,代码中不写的情况下默认返回true,如果写了shouldComponentUpdate函数,则以写的为主,需要有返回值,为bool类型,判断是否允许更新,如果返回值为false,将不会往下执行
2. forceUpdate(强制更新) → componentWillUpdate(将要进行更新) → render(更新) → componentDidUpdate(更新完毕)→ componentWillUnmount
不对状态有任何的修改,只是更新页面,与setState使用方法类似 this.forceUpdate()
3. 通过父组件更新componentWillReceiveProps → shouldComponentUpdate(控制更新开关) → componentWillUpdate(将要进行更新) → render(更新) → componentDidUpdate(更新完毕)→ componentWillUnmount
注意:componentWillReceiveProps 首次渲染不会生效,只有再次更新的时候才会生效即第二次调用render
// 父组件
class A extends React.Component{
// 初始化状态
state = {carName:'奔驰'}
changeCar = ()=>{
this.setState({carName:'奥迪'})
}
render(){
return(
<div>
<div>A组件</div>
<button onClick={this.changeCar}>换车</button>
<B carName={this.state.carName}/>
</div>
)
}
}
// 子组件
class B extends React.Component{
componentWillReceiveProps(){
console.log('B----componentWillReceiveProps');
}
render(){
return(
<div>B组件,接收到的车是:{this.props.carName}</div>
)
}
}
// 渲染组件
ReactDOM.render(<A />,document.getElementById('test'))
总结:
- 初始化阶段:由RenderDOM.render() 触发 — 初次渲染
- constructor()
- componentWillMount()
- render()
- componentDidMount() —> 常用,一般在这个钩子做初始化的事,例如:开启定时器,发送请求,订阅消息
- 更新阶段:由组件内部this.setState()或父组件render触发
- shouldComponentUpdate()
- componentWillUpdate()
- render() —>必须使用的一个
- componentDidUpdate()
- 卸载组件:由ReactDOM.unmountComponentAtNode() 触发
- componentWillUnmount() —> 常用,一般在这个钩子做收尾的事,例如:关闭定时器,取消订阅消息
生命周期(新)
变化:
-
改名:componentWillMount —> UNSAFE_componentWillMount, componentWillReceiveProps—>UNSAFE_componentWillReceiveProps, componentWillUpdate—>UNSAFE_componentWillUpdate
(在未来可能会废弃,避免使用)
-
增加两个钩子:get
getDerivedStateFromProps
由于getDerivedStateFromProps是横跨三个状态的,创建时,更新,卸载都有起作用,所以会影响之后的流程
// 得到一个派生状态对象,在调用的时候直接传props,直接改变状态
// 在这里改变了状态之后会影响其他的方法改变状态
// 即state的值在任何时候都取决于props
// 需要是静态方法,返回为null或者是静态对象
static getDerivedStateFromProps(props, state) {
console.log('getDerivedStateFromProps', props, state);
return { count: 108 }
// return null
}
getSnapshotBeforeUpdate
在更新之前获取快照,保存更新之前的参数状态,通过return保存下来
// 必须有返回值,在componentDidUpdate 可以收到
// 在更新之前获取快照
getSnapshotBeforeUpdate() {
console.log('getSnapshotBeforeUpdate');
return 'snapshot'
}
// 组件更新完毕的钩子 更新之前的props state 有点像监听函数,可以获取到改变之前的值
componentDidUpdate(preProps, preState, snapshotVale) {
console.log('Count---componentDidUpdate', preProps, preState, snapshotVale);
}
三个重要的生命周期函数(新旧一样)
- render 初始化渲染或更新渲染调用
- componentDidMount 开启监听,发送ajax
- componentWillUnmount 做一些收尾工作,如:清理定时器
脚手架
index.html详细说明
<head>
<meta charset="utf-8" />
<!-- %PUBLIC_URL% 代表public文件夹路径 -->
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- 开启理想视口,用于做移动端的适配 -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- 用于配置浏览器页签+地址栏的颜色(仅限于安卓手机浏览器) -->
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<!-- 用于指定网页添加手机主屏幕后的图标 -->
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!-- 应用加壳时的配置文件 -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
目录结构
通信
父子间通信
1. 父传子prop
// 父组件:
state = { todos: [{id:'001', name:'eat', done: true}] }
<List todos={this.state.todos} />
// 子组件:
this.props.todos
2. 通过函数调用改变父组件的值
// 子组件:
this.props.a(value)
// 父组件:
a = (data) =>{
console.log(data)
}
<Header a={this.a} />
消息订阅与发布
订阅时,在componentDidMount处订阅,PubSub.subscribe('消息名称', (msg:'消息名', data: '函数或数据'),订阅完需要销毁
// 消息订阅与发布 放在此钩子
componentDidMount(){
this.token = PubSub.subscribe('updateUsers', (msg, stateObj)=>{
this.setState(stateObj)
})
}
// 销毁时 取消订阅
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
发布时
PubSub.publish('updateUsers', {isFirst: false, isLoading: true})
配置代理
方法一:直接在package.json里面去写配置,弊端:只能配置一个代理
方法二:在src目录下增加 setupProxy.js文件,ajax请求会自动找到此文件,然后加入到webpack配置文件中,用的是commonjs规范
// setupProxy.js
const proxy = require('http-proxy-middleware')
module.exports = function(app){
app.use(
proxy('/api1',{ // /api1 代理标识
target:'http://localhost:5000', // 请求地址
changeOrigin: true, // 控制服务器收到的请求头中host的值,false发出去是真实的客户端地址,true则为服务器地址
pathRewrite: {'^/api1':''} // 重写路径,把代理标识取代(必须)
}),
proxy('/api2',{
target:'http://localhost:5001',
changeOrigin: true,
pathRewrite: {'^/api2':''}
}),
)
}