赞
踩
抹平不同浏览器之间的兼容性差异。最主要的冬季
既可以处理兼容性问题
提供一个抽象的跨平台事件机制
可以做更多优化
可以干预事件的分发
react会对事件先进行注册,将事件统一注册到document上
根据组件唯一的标识key来对事件函数进行存储
统一的指定dispatchEvent回调函数
储存事件回调:react会将click这个事件统一存到一个对象中,回调函数的存储采用键值对(key/value)的方式存储在对象中,key是组件的唯一标识id,value对应的就是事件的回调函数,通过组件的key就能回调到相应的函数了
setState是修改其中的部分状态,相当于Object.assign,只是覆盖,不会减少原来的状态;replaceState是完全替换原来的状态,相当于赋值,将原来的state替换成另一个对象,如果新状态属性减少,那么state中就没有这个状态了
action
action理解为动作,action的值一般为一个对象,格式如{ type:“”, data:“” },type是必须要的,因为reducer处理数据的时候要根据不同的type来进行不同操作
reducer
reducer是初始化以及处理派发的action的纯函数,作用是接收旧的state和action,返回新的state
store
store是一个仓库,用来存储数据,它可以获取数据,也可以派发数据,还能监听到数据的变化
受控组件就是可以被react状态控制的组件
在react中,Input textarea等组件默认是非受控组件(输入框内部的值是用户控制,和React无关)。但是也可以转换成受控组件,就是通过onChange事件获取当前输入内容,将当前输入内容作为value传入,此时就称为受控组件
如果项目体量较小,只是需要一个公共的store存储state,而不讲究使用action来管理state,那context完全可以胜任。反之,则是redux的优点。
使用场景:
组件间传递的数据逻辑比较复杂,可以使用redux
组件层级不多,可以使用props
层级较深,数据逻辑简单,可以使用context
componentDidMount:useEffect(()=>{console.log(‘第一次渲染时调用’)},[ ])
useEffect(()=>{console.log(‘任意状态改变’)})
监听多个属性的变化需要将属性作为数组传入第二个参数
useEffect(()=>{console.log(‘指定状态改变’)},[状态1,状态2…])
-模拟componentWillUNmount
useEffect(()=>{ … return()=>{ //组件卸载前} })
updater:object/function 用于更新数据
callback:function 用于获取更新后最新的state值
构造函数是唯一建议给this.state赋值的地方
不建议直接修改state的值,因为这样不会重新渲染组件
自动进行浅合并(只会合并第一层)
由于setState()异步更新的缘故,依赖state旧值更新state的时候建议采用传入函数的方式
const [ state , setState ] = useState(initState)
state:状态
setState(updater):修改状态的方法
updater:object/function 用于更新数据
initState:状态的初始值
当props发生变化时执行,初始化render时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用
//props发生变化时触发
componentWillReceiveProps(props) {
console.log(props)
this.setState({show: props.checked})
}
返回一个memoized值
把“创建”函数和依赖项数作为参数传入useMemo,它仅会在某个依赖项改变时才重新计算memoized值。这种优化有助于避免在每次渲染时都进行高开销的计算
传入useMemo的函数会在渲染期间执行。请不要再这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于useEffect的使用范畴,而不是useMemo
如果没有提供依赖项数组,useMemo在每次渲染时都会计算新的值
可以把useMemo作为性能优化的手段,但不要把它当成语义上的保证。将来React可能会选择“遗忘”以前的一些memoized值,并在下次渲染时重新计算它们,比如为离屏组件释放內存。先编写在没有useMemo的情况下也可以执行的代码 —— 之后再在你的代码中添加useMemo,以达到优化性能的目的。
useState是用于声明一个状态变量的,用于为函数组件引入状态
useState只接收一个参数,这个参数可以是数字、字符串、对象等任意值,用于初始化声明的状态变量。也可以是一个返回初始值的函数,最好是函数,可以在渲染时减少不必要的计算
返回一个长度为2的读写数组,数组的第一项是定义的状态变量本身,第二项是一个用来更新该状态变量的函数,约定是set前缀加上状态的变量名
useState Hook中返回的setState并不会帮我们自动合并对象状态的属性
useState中接收的对象参数如果地址没变的话会被React认为没有改变,因此不会引起视图的更新
useReducer是useState的升级版。在useState中返回的接口中,我们只能传递最终的结果,在setN的内部也只是简单的赋值操作
创建初始状态值initialState
创建包含所有操作的reducer(state,action)函数,每种操作类型均返回新的state值
根据initialState和reducer使用const [ state, dispatch ] = useReducer(reducer,initialState)得到读写API
调用接口,传递的参数均挂在action对象上
context是上下文,上下文是局部的全局变量,这个局部的范围由开发者自己定义
effect是副作用的意思,对环境的改变就是副作用。副作用是函数式编程里的一个概念
在React中,useEffect就是在每次render后执行的操作,相当于afterRender,接收的第一个参数是回调函数,第二个参数是回调时机。可用在函数组件中模拟生命周期。
如果同时出现多个useEffect,会按出现顺序依次执行
useEffect总是在浏览器渲染完视图过后才执行,如果useEffect里面的回调函数有对DOM视图的操作,则会出现一开始是初始化的视图,后来执行了useEffect里的回调后立马改变了视图的某一部分,会出现一个闪烁的状态。
为了避免这种闪烁,可以将副作用的回调函数提前到浏览器渲染视图的前面执行,当还没有将DOM挂载到页面显示前执行Effect中对DOM进行操作的回调函数,则在浏览器渲染到页面后不会出现闪烁的状态。
layout是视图的意思,useLayoutEffect就是在视图显示处理前执行的副作用
useEffect和useLayoutEffect就是执行的时间点不同,useLayoutEffect是在浏览器渲染前执行,useEffect是在浏览器渲染后执行。但二者都是在render函数执行过程中运行,useEffect是在render完毕后执行,useLayoutEffect是在render完毕前(视图还没渲染到浏览器页面上)执行。因此useLayoutEffect总是在useEffect前执行
一般情况下,如果Effect中的回调函数中涉及到DOM视图的改变,就应该用useLayoutEffect,如果没有,则用useEffect
useRef Hook是用来定义一个组件在不断render时保持不变的变量
组件每次render后都会返回一个虚拟DOM,组件内对应的变量都只属于那个时刻的虚拟DOM。
useRef Hook提供了创建贯穿整个虚拟DOM更新历史的属于这个组件的局部的全局变量
为了确保每次render后使用useRef获得的变量都能是之前的同一个变量,只能使用引用做到,因此,useRef就将这个局部的全局变量的值存储到了一个对象中,属性名为current
useRef的current变化时不会自动render
useRef可以将创建的Refs对象通过ref属性的方式引用到DOM节点或者React实例
将某个函数“放入到react底层原型链上,并返回该函数的索引”,而useMemo是将某个函数返回值“放入到react底层原型链上,并返回该返回值的索引”。一个是针对函数,一个是针对函数返回值
uselmperativeHandle可以让父组件获取并执行子组件内某些自定义函数(方法)。本质上其实是子组件将自己内部的函数(方法)通过uselmperaativeHandle添加到父组件中useRef定义的对象中
useMemo可以将某些函数的计算结果(返回值)挂载到react底层原型链上,并返回该函数返回值的索引。当组件重新渲染时,如果useMemo依赖的数据变量未发生变化,那么直接使用原型链上保存的该函数计算结果,跳过本次无异议的重新计算,达到提高组件性能的目的
Component没有直接实现shouldComponentUpdate这个方法;但是PureComponent通过浅层的Porps和state的对比,内部实现了这个生命周期函数
PureComponent会跳过整个组件子树的props更新,要确保全部的子组件也是pure形式
Component中需要手动执行的shouldComponentUpdate函数,在PureComponent中已经自动完成了(自动浅对比)
PureComponent不仅会影响本身,而且会影响子组件,所以PureComponent最好用在数据展示组件中
PureComponent如果是复杂数据类型,这里会造成错误的提示(setState浅复制更新,但是界面不会重新渲染)
Hooks解决方式:函数组件和普通JS函数非常相似,在普通JS函数中定义的变量、方法都可以不适用“this”,而直接适用该变量或函数,因为不需要去关心“this”了
Hooks解决方式:通过自定义Hook,可以将数据状态逻辑从组件中抽离出去,这样同一个Hook可以被多个组件使用,解决组件数据状态逻辑并不能重用的问题
Hooks解决方式:通过React内置的useState()函数,可以将不同数据分别从“this.state”中独立拆分出去。降低数据复杂度和可维护性,同时解决类组件缺点中“内部state数据只能是整体,无法被拆分更细”的问题
通过React内置的useEffect()函数,将componentDidMount、componentDidUpdate、componentWillUncount三个生命周期函数通过Hook(钩子)关联成1个处理函数,解决事件订阅分散在多个生命周期函数的问题
父组件使用useRef创建一个ref传入子组件
子组件需要使用useImperativeHandle暴露ref自定义的实例值给父组件。这个需要用forwardRef包裹着。
类组件修改数据的方法是通过setState
setState的修改方法有两种,而且它是异步的
函数组件修改方式通过自定义方法。需要通过useState,hooks
React native基于JavaScript开发的一个可以开发原生app的集成框架,它兼容开发IOS和Android,能够实现一套代码,两个系统都能使用,方便维护,相比web前端的react,react-native更好的提供了一些调用手机硬件的API,可以更好的开发移动端,现在react-native它的生态环境也是越来越好,基本上可以完全实现原生开发
但是现在很多的应用还是用它来套壳(原生+web前端),用它来做有些路由,和框架的搭建,然后里面内容来使用前端的react来实现,这样一来让维护更方便,开发更便捷
redux它是一个单独的状态管理工具,它是一个数据集中管理的方案,简单的说,就是将公用的数据,放在redux里面进行存储,修改的时候也是利用redux提供的方法来修改,让框架使用的数据的时候更方便,维护起来更容易,redux提供了以下核心内容
store是redux的核心内容,整个redux的仓库,所有的应用方法都是由store提供
createStore用于创建store,方法里面有三哥参数,有reducer,有中间件,还有初始值,最重要的就是reducer函数,它提供了整个数据管理的逻辑
reducer函数相当于数据加工厂,初始的数据,修改数据的逻辑都统统的在这里完成,它让我们整个的数据走向更完整,维护更方便
action本质是一个对象,它来告诉redux要执行什么任务
state它就是我们需要存储的redux数据,所有的数据都将要在这里面存储
它就是用来获取数据的,每次修改前后的数据都可以用store.getState()来修改
用户通过dispatch触发要执行的任务,这个就是触发动作,然后reducer函数会执行,然后进行数据加工
会自动的监听state,一旦有state发生改变,store.subscribe就回执行,利用它可以用来更新视图
react生命周期有三个阶段,两个阶段都会执行render
主要从更新和挂载两个阶段来讲,挂载阶段的顺序,更新阶段一定要说shouldComponentUpdate,true和false分别对应后边是否执行render
1) 挂载阶段
constructor(){}
static getDerivedStateFromProps(){
return {}
}
render(){}. 挂载阶段会执行一次
componentDidMount(){}
2 ) 更新阶段
static getDerivedStateFromProps(props, state){rerturn {}}
shouldComponentUpdate(nextProps, nextState).{ return Boolean. 注意如果 false 则
不向下执行 ,true的时候会执行render}
return。true
render() …
useEffect的依赖为引用类型的时候,可能会导致监听不触发,原因就是监听的同一个地址的时候,对象本身地址没变,所以监听的结果就是任务数据并没有改变从而不直接调用
解决方案
1.如果是数据是对象的话,可以监听对象里面的值,值是基本类型,如果值改变了,那么可以监听执行
2.在去修改对象和数据的时候,使用深拷贝或者浅拷贝,这样地址发送改变可以监听执行
3.可以转成字符串,通过JSON.stringify(),监听字符串,这样改变也会执行
const [count, setCount] = useState(0) const add = () => { setCount(count + 1) setCount(count + 1) setCount(count + 1) setCount(count + 1) //就算执行多次,其实还是只会执行一次 //clas组件是一样的 } // 修改后 const add = () => { setCount(count => count + 1); //这种回调函数的写法 setCount(count => count + 1); setCount(count => count + 1); setCount(count => count + 1); // class组件 this.setState(prev => ({ count: prev.count })) };
const [count, setCount] = useState(0); const add = () => { setCount(count + 1); if (count >= 10) { // 一个逻辑 这样的写的话 会执行上一次的结果} }; // 正确使用 1 const add = () => { let n = count + 1 if (n) { //逻辑 } setCount(n) }; // 正确2 : const add = () => [ setCount(count + 1) ] useEffect(() => { // 这里是逻辑 }, [count])
useEffect(() => {
// 逻辑1
return () => {
// 清楚逻辑1的副作用
}
}, [/* 监听的值 */])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。