not finished
一、redux
redux是一种JavaScript状态管理器。可与很多类库一起使用。此处介绍与react结合。 redux有三个常用的方法:
import {createStore,applyMiddleware} from 'redux';
import createSagaMiddleware from 'redux-saga';
var sagaMiddle = createSagaMiddle();
var sotre = createStore(reducer,applyMiddleware(sagaMiddle));
sagaMiddleware.run(fun);//saga中间件的实例运行生成函数
//中间键,处理异步的actionredux数据传递的流程
//saga文件
import {takeEvery,call,put} from 'redux/saga/effets';
//可以监听发出的所有动作
function *test(){
var result = yield call(()=>{
return fetch(“url”).then((res)=>res.json())
})
console.log(result);
yield put({
type:”GETADA”,
list:result
})
}
export default function *watchAll(){
yield takeEvery(‘WATCHALL’,test)
}
运用context将react和redux连接起来
import {Provider} from 'react-redux';
<Rrovider store={store}>
<Router></Router>
</Provider>
-
reducer,以及如何合并
reducer是一个纯函数,reducer(state,action)。
state是只读不改。
每个模块都有一个reducer,用combineReducers()合并。
-
redux中间件
中间件是在dispatch和reducer之间的一个应用。
组件需要改变数据的时候store把action传递给reducer,reducer做处理以后会传递给store。
store通过subscribe()调用函数,执行setState使得view视图发生改变
二、 react-router
withRouter
不是通过路由切换过来的组件,没有history,location,match这三个对象
import {withRouter} from 'react-router'
withRouter(App)
react中路由传递参数的方法
动态路由传参数
query传值
react的编程式导航的方法
this.props.history.push("需要跳转的路径")
this.props.history.back()
this.props.history.forward()
this.props.history.replay()
Route的两种渲染方式
<Route path="/home" component={}/>
<Route path="/home" render={()=>{return <Home />}}>
通过render进行组件渲染,优点在于可以进行组件传参,还可以渲染非主组件的标签,缺点在于若使用history ,location,match需要在函数中传递过去???
三、React
类组件和函数组件
生命周期
挂载阶段
-
1 constructor(props,context)
初始化:初始化state,将事件处理函数绑定到实例上。
-
2 static getDerivedStateFromProps(props,state)
derived state派生状态
组件实例化后,props更新了调用。若父组件的props更改所带来的的重新渲染,也会触发此方法。
必须返回一个对象来更新状态或者返回null表示新的props不需要任何state的更新。
静态方法不能用this,调用是lei.静态方法名()
-
3 render()
必需的,当被调用时,将计算this.props和this.state。并返回以下一种类型
1.React元素。通过jsx创建,可是dom元素,也可是用户自定义的组件
2.字符串或数字。他们将以文本节点形式渲染到dom中。
- null,什么也不渲染。
- 布尔值。也是什么都不渲染
- 数组:以字符串形式渲染
注:对象不能直接渲染
-
componentDidMount()
组件被装配后立即调用。初始化使得dom节点应该进行到这里
可操作DOM节点。
通常在这里进行ajax请求。初始化第三方的dom库,
更新节点
-
static getDerivedStateFromProps(props,state)
-
shouldComponentUpdate(nextProps,nextState)
默认ture,会render。可以加条件减少不必要的渲染,增加性能。
若返回false,componentWillUpdate、render、componentDidUpdate不会调用
-
PureComponent 进行浅比对,进行性能的优化(纯组件) extends.PureComponent
参数和返回值都是组件:高阶函数(map,filter,forEach.....)
仅进行浅层对比,若对象中包含复杂的数据结构,则可能产生错误比对。
仅在state和props较简单的时候用。
-
对函数组件用React.memo(组件)
仅检查props有没改变
const MyComponent = React.memo(function MyComponent(props) { /* 使用 props 渲染 */ });默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。
function MyComponent(props) { /* 使用 props 渲染 */ } function areEqual(prevProps, nextProps) { /* 如果把 nextProps 传入 render 方法的返回结果与 将 prevProps 传入 render 方法的返回结果一致则返回 true, 否则返回 false */ } export default React.memo(MyComponent, areEqual);
-
-
render()
-
getSnapshotBeforeUpdate(prevProps,prevState)
使组件能够在它们被潜在更改之前捕获当前位置(如滚动位置)
必须与componentDidUpdate一起用
必须返回一个值 返回的任何值会作为参数传递给componentDidUpdate()
不能和旧版的钩子函数一起用
目的是为了返回数据更新前的dom状态
-
componnetDidUpdate(prevProps,prevState,snapshot)
将当前props和以前props比较。
可单独使用
-
componentWillReceiveProps(nextProps)
当props发生变化时,初始化render时不执行。一般用于父组件状态更新子组件的重新渲染。
可在子组件的render中获取最新的props,更新子组件的state。可将子组件的数据处理及接口在这里执行,而不用都放在父组件中。于是改请求只会在该组件渲染时才发出,减少了请求的负担。
卸载阶段
-
componentWillUnmount()
组件被卸载并销毁之前被调用。
清理:定时器无效,取消网络请求、清理在componentDidMount中创建的任何监听
-
错误处理
- static getDerivedStateFromError()
- componentDidCatch()
11 Props默认值,限定类型
设置props默认值:调用this.props
defaultProps用于确保this.props.key在父组件没有指定其值的时,有一个默认值。
类组件
//类组件
static defaultProps = {
key:默认值
}
//无状态组件
组件名.defaultProps={
key:默认值
}
props限定类型
propTypes类型检查发生在defaultProps赋值后,所以类型检查也使用于defaultProps
//类组件
import PropTypes from 'prop-types'
static propTypes = {
key:PropTypes.类型
name: React.PropTypes.string.isRequired
}
//无状态组件
组件名.propTypes={
key.propTypes.类型.isRequired(必须传)
data: PropTypes.object.isRequired
}
createProtal(childrem,domNode,key)
不挂载在父组件下,挂在任意dom上。常见场景:弹窗
import { createProtal } from 'react-dom'
<div>
<p>这个子节点被放置在父节点div中</p>
{createPortal(
<p>这个子节点被放置在document body中</p>,
document.body
)}
</div>
setState
setState({},callback)
//wrong
this.setState({
counter:this.state.counter+this.props.increment
},callback);
//correct
this.setState((prevState,props)=>{
counter:prevState.counter+props.increment
},callback)
this.setState({key:新的value},()=>{回调函数}) 连续多个对象参数会合并,以最后一个为准, 连续执行多次,放入队列中一次执行
callback用来验证数据是否修改成功,同时可以获取到数据更新后的DOM结构,同componentDidMount
高阶组件
参数和返回值都是组件。
作用:
- 属性代理——进行组件的复用(比如算积分)
- 反向集成——对渲染的劫持(比如购物车组件没有登录就不能渲染)
常用的hook
useState
useRef
- 绑定dom元素
- 绑定值,当该值变化的时候,不会触发重新渲染。
const intervlRef = useRef(0)
function handleClick = () => {
intervlRef.current = ref.current +1 // 不会重新渲染render
}
console.log('intervalRef.current', intervalRef.current) // 始终是初始值
useEffect
useEffectEvent
useLayoutEffect
在浏览器重新绘制屏幕之前就触发了
useImperativeHandle
useCallback
useMemo
useID
useContext
useInsertionEffect
在react中解决单页面开发首次加载白屏现象
- 路由懒加载方式:react-loadable
- 首屏服务端渲染
react中key的理解
diff算法是比较同级元素。
react用key识别组件。
key值相同,若属性有变化,则更新组件对用的属性。没有变化,就不需要更新
key值不同,则先销毁该组件,然后创建该组件。
对context的理解
组件传值是通过props传递的,不能跨组件传递,若要跨组件则可用context。
子孙组件就可调用store
其他
- 只要父组件重新渲染, 即使子组件的props未变化,子组件也会重新渲染,触发render。
- Diff算法。Virtual Dom 虚拟dom。
- React基于虚拟DOM和diff算法,以及性能很好了,但依旧可以配合shouldComponentUpdate和PureComponent使用。React.memo()
- 强制更新DOM,this.foreUpdate()