bind 由于在类中,采用的是严格模式,所以事件回调的时候会丢失this指向,指向的undefined,需要使用bind来给函数绑定上当前实例的this指向。
箭头函数的this指向上下文,所以永久能拿到当前组件实例的。this指向我们可以完美的使用箭头函数来替代传统事件处理函数的回调。
Redux由Action、Reducer和Store三部分构成,他们的解释如下:
而reducer的作用就是接收旧的 state 和 action,返回新的 state。
受控组件就是可以被 react 状态控制的组件。在 react 中,Input textarea 等组件默认是非受控组件(输入框内部的值是用户控制,和React无关)。但是也可以转化成受控组件,就是通过 onChange 事件获取当前输入内容,将当前输入内容作为 value 传入,此时就成为受控组件。
如果项目体量较小,只是需要一个公共的store存储state,而不讲究使用action来管理state,那context完全可以胜任。反之,则是redux的使用场景。
在进行状态管理时,通常遵循以下的原则:
componentDidMount:useEffect(()=>{console.log('第一次渲染时调用')},[])
useEffect(()=>{console.log('任意状态改变')})
如果需要监听多个属性的变化则需要将属性作为数组传入第二个参数。
useEffect(()=>{console.log('指定状态改变')},[状态1,状态2...])
useEffect(()=>{ ... return()=>{ //组件卸载前} })
当props发生变化时执行,初始化render时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用。
componentWillReceiveProps(props) {
console.log(props)
this.setState({show: props.checked})
}
返回一个 memoized 值。
把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于 useEffect 的适用范畴,而不是 useMemo。
如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值。
你可以把 useMemo 作为性能优化的手段,但不要把它当成语义上的保证。将来,React 可能会选择“遗忘”以前的一些 memoized 值,并在下次渲染时重新计算它们,比如为离屏组件释放内存。先编写在没有 useMemo 的情况下也可以执行的代码 —— 之后再在你的代码中添加 useMemo,以达到优化性能的目的。
Component 没有直接实现 shouldComponentUpdate 这个方法,但是 PureComponent通过浅层的Porps 和 state 的对比,内部实现了这个生命周期函数。
PureComponent会跳过整个组件子树的props更新,要确保全部的子组件也是 pure 的形式。
Component 中需要手动执行的 shouldComponentUpdate 函数,在PureComponent中已经自动完成了(自动浅对比)。
PureComponent不仅会影响本身,而且会影响子组件,所以PureComponent最好用在数据展示组件中。
PureCoponent 如果是复杂数据类型,这里会造成错误的显示(setState浅复制更新,但是界面不会重新渲染)。
首先,我们来看一下类组件的一些缺点:
缺点1:复杂且不容易理解的“this”。
Hooks解决方式:函数组件和普通JS函数非常相似,在普通JS函数中定义的变量、方法都可以不使用“this.”,而直接使用该变量或函数,因此你不再需要去关心“this”了。
缺点2:组件数据状态逻辑不能重用
Hooks解决方式:通过自定义Hook,可以数据状态逻辑从组件中抽离出去,这样同一个Hook可以被多个组件使用,解决组件数据状态逻辑并不能重用的问题。
缺点3:组件之间传值过程复杂
Hooks解决方式:通过React内置的useState()函数,可以将不同数据分别从"this.state"中独立拆分出去。降低数据复杂度和可维护性,同时解决类组件缺点三中“内部state数据只能是整体,无法被拆分更细”的问题。
通过React内置的useEffect()函数,将componentDidMount、componentDidUpdate、componentWillUncount 3个生命周期函数通过Hook(钩子)关联成1个处理函数,解决事件订阅分散在多个生命周期函数的问题。
父组件使用 useRef 创建一个 ref 传入 子组件 子组件需要使用。useImperativeHandle 暴露 ref 自定义的实例值给父组件,并且需要使用 forwardRef 包裹着。
类组件修改数据的方法, 通过setState , 注意setState的修改方法有两种,而且它是异步的
函数组件修改方式通过自定义的方法。需要通过 useState , 例如。const [count,setCount] = useState(0)。
React native 基于 JavaScript 开发的一个 可以开发原生app的这么一个集成框架,它兼容开发 iOS 和 Android能够实现一套代码,两个系统都能使用,方便维护,相比于web前端的 react ,react-native更好的提供了一些调用手机硬件的API,可以更好的开发移动端,现在react-native它的生态环境也是越来越好,基本上可以完全实现原生开发,
但是现在好多的应用还是用它来套壳 (原生 + web前端),用它来做有些路由,和框架的搭建,然后里面内容来使用前端的react来实现,这样一来让维护更方便,开发更快捷
方法1:通过受控组件,可以获取到state里面的值,获取修改结果,代码如下。
class Home extends React.Component {
state = {
val:""
}
//这是一个通用的写法,然后注意 name的值一定要与state定义的一直
changeInput = (e) =>{
let {name,value} = e.target
this.setState({
[name]:value
})
}
render(){
return <>
<input onChange="this.state.val" />
</>
}
}
方法2:通过ref来获取里面的值。
class Home extends React.Component {
render(){
//this.val 获取里面的真是dom
return <input ref={node=>this.val} />
}
}
React生命周期有三个阶段。 两个阶段都会执行 render 主要从更新和挂载两个阶段来讲,挂载阶段会执行一次,更新阶段主要会涉及shouldComponentUpdate。
首先,我们看一下挂载阶段:
constructor(){}
static getDerivedStateFromProps(){
return {}
}
render(){} //挂载阶段会执行一次
componentDidMount(){}
接下来,我们看一下更新阶段:
static getDerivedStateFromProps(props, state){rerturn {}}
shouldComponentUpdate(nextProps, nextState).{
return Boolean //注意如果 false 则 不向下执行 ,true的时候会执行render
}
render() ..
useEffect的依赖为引用类型的时候,可能会导致监听不出发,原因就是监听的统一个地址的时候,对象本身地址没变,所以监听的结果就是认为数据并没有改变从而不直接调用。
解决的方法有以下几点:
React的key值给组件作为唯一标识,类似身份证,当数组发生增删改查的时候可以通过这个 标识来去对比虚拟dom的更改前后,如果相同标识的数据或者属性没有改变的话,讲直接略过,对比有改变的然后直接改变此项。
如果给组件添加key,如果key值改变的时候,组件将会触发如下的生命周期:
react.createPortal() 这个方法是来使用做弹窗Modal组件的,在没有这个组件之前我们可以自己定义组件,然后去实现Modal效果。
const styles = {
modal: {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0,0,0,0.3)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}
}
class Modal extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div style={styles.modal}>
{this.props.children}
</div>
);
}
}
react.createPortal 这个来制作弹窗组件,它 在Modal 组件位置进行 fixed 定位,可以任意的挂载到某个dom元素上,使用后的管理更方便,但是注意需要预留html的挂载元素。
真正意义上的react全家桶,其实指的是react,react-dom,react-native。因为react核心库只是vDom的操作,无关dom(dom操作在react-dom中)——这意味着它天生就可以做到跨平台。
注意这里有误区,react-router,react-router-dom,react-dux只是社区的一些使用较多的解决方案,事实上它们各有缺陷。
React Fiber 是 React 框架的一种底层架构,为了改进 React 的渲染引擎,使其更加高效、灵活和可扩展而提供的。
传统上,React 使用一种称为堆栈调和递归算法来处理虚拟 DOM 的更新,这种方法在大型应用或者频繁更新的情况下可能会产生性能问题。React Fiber 则是基于一种增量渲染的思想,它将更新任务分解成小的、可中断的单元,使得 React 在更新时可以更灵活地控制和切换任务,提高应用的响应性。
React Fiber 的核心功能包括:
react-hooks提供给了函数式组件以业务逻辑抽离封装的能力,从单一组件单位进行UI与业务逻辑的分离,以此来保证函数式组件的UI纯净。
Hooks的出现解决了两个问题:
组件的逻辑复用:在hooks出现之前,react先后尝试了 mixins混入,HOC高阶组件,render-props等模式但是都有各自的问题,比如mixin的数据来源不清晰,高阶组件的嵌套问题等等
Class组件自身的问题:class组件本身提供了很多东西,有不可忽视的学习成本,比如各种生命周期,this指向问题等等。
副作用函数
我们将跟UI渲染无关的业务逻辑称之为副作用。
useEffect是react在函数式组件里提供的副作用解决方案,它接受两个参数。第一个是必传参数,类型为函数。我们写在此函数中的业务逻辑代码就是我们所说的副作用。
消除副作用
默认情况下,useEffct会在每次render后执行传入的副作用函数。然而有的时候我们需要在执行副作用前先去除掉上次render添加的副作用效果,我们可以在副作用函数里再返回一个函数,这个函数就是消除副作用,它会在每次reRender前和组件卸载时去执行。
监听器
与 useMemo, useCallback等一样,useEffect可以传入一个监听数组参数,这意味着副作用只有在数组中的监听值变化时才会执行。借助它的这个参数特性,可以模拟类组件生命周期钩子,比如componentDidMount等。