react

说说react中onClick绑定后的工作原理

  • 首先react有自己的事件系统,也是遵循w3c的,这个事件系统的名称叫做合成事件(SyntheticEvent),而其自定义事件系统的动机主要包含以下几个方面

抹平不同浏览器之间的兼容性差异。最主要的冬季
既可以处理兼容性问题
提供一个抽象的跨平台事件机制
可以做更多优化
可以干预事件的分发

  • 当给组件(元素)绑定onClick事件之后

react会对事件先进行注册,将事件统一注册到document上
根据组件唯一的标识key来对事件函数进行存储
统一的指定dispatchEvent回调函数
储存事件回调:react会将click这个事件统一存到一个对象中,回调函数的存储采用键值对(key/value)的方式存储在对象中,key是组件的唯一标识id,value对应的就是事件的回调函数,通过组件的key就能回调到相应的函数了

react中的性能优化

  • 使用shouldComponentUpdate来对state和props进行对比,如果两次的结果一致,那么就return false
  • 使用纯净组件pureComponent

react里面bind与箭头函数

  • bind由于在类中采用的是严格模式,所以事件回调的时候会丢失this指向,指向undefined,需要使用bind来给函数绑定上当前实例的this指向
  • 箭头函数的this指向上下文,所以永久能拿到当前组件实例的this指向,我们可以完美的使用箭头函数来替代传统事件处理函数的回调

高阶组件和高阶函数是什么

  • 高阶函数:函数接收一个函数函数作为参数,或者将函数作为返回值的函数就是高阶函数 map some every filter reduce find forEach等都属于高阶函数
  • 高阶组件:接受一个组件,返回一个新组建的组件就是高阶组件,本质上和高阶函数一样
  • 高阶组件是用来复用react代码的一种方式

类组件setState是同步还是异步

  • 使用合成事件setState是异步的,想要拿到最新数据需要去回调
  • 使用原生事件setState是同步的

setState和replaceState的区别

setState是修改其中的部分状态,相当于Object.assign,只是覆盖,不会减少原来的状态;replaceState是完全替换原来的状态,相当于赋值,将原来的state替换成另一个对象,如果新状态属性减少,那么state中就没有这个状态了

redux三大核心

action

action理解为动作,action的值一般为一个对象,格式如{ type:“”, data:“” },type是必须要的,因为reducer处理数据的时候要根据不同的type来进行不同操作

reducer

reducer是初始化以及处理派发的action的纯函数,作用是接收旧的state和action,返回新的state

store

store是一个仓库,用来存储数据,它可以获取数据,也可以派发数据,还能监听到数据的变化

什么是受控组件

受控组件就是可以被react状态控制的组件
在react中,Input textarea等组件默认是非受控组件(输入框内部的值是用户控制,和React无关)。但是也可以转换成受控组件,就是通过onChange事件获取当前输入内容,将当前输入内容作为value传入,此时就称为受控组件

hooks+context和redux你是怎么选择的,都在上面场景下使用

如果项目体量较小,只是需要一个公共的store存储state,而不讲究使用action来管理state,那context完全可以胜任。反之,则是redux的优点。
使用场景:

组件间传递的数据逻辑比较复杂,可以使用redux
组件层级不多,可以使用props
层级较深,数据逻辑简单,可以使用context

useffect模拟生命周期

  • 模拟componentDidMount
    第二个参数为一个空数组,可以模拟componentDidMount

componentDidMount:useEffect(()=>{console.log(‘第一次渲染时调用’)},[ ])

  • 模拟componentDidUpdate
    没有第二个参数代表监听所有的属性更新

useEffect(()=>{console.log(‘任意状态改变’)})

监听多个属性的变化需要将属性作为数组传入第二个参数

useEffect(()=>{console.log(‘指定状态改变’)},[状态1,状态2…])

-模拟componentWillUNmount

useEffect(()=>{ … return()=>{ //组件卸载前} })

setState更新之后和useState的区别

  • setState( updater [,callback])

updater:object/function 用于更新数据
callback:function 用于获取更新后最新的state值

构造函数是唯一建议给this.state赋值的地方
不建议直接修改state的值,因为这样不会重新渲染组件
自动进行浅合并(只会合并第一层)
由于setState()异步更新的缘故,依赖state旧值更新state的时候建议采用传入函数的方式

  • useState(initState)

const [ state , setState ] = useState(initState)
state:状态
setState(updater):修改状态的方法
updater:object/function 用于更新数据
initState:状态的初始值

react父组件props变化的时候子组件怎么监听

当props发生变化时执行,初始化render时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用

//props发生变化时触发
componentWillReceiveProps(props) {
	console.log(props)
	this.setState({show: props.checked})
}

usememo在react中怎么使用

返回一个memoized值

把“创建”函数和依赖项数作为参数传入useMemo,它仅会在某个依赖项改变时才重新计算memoized值。这种优化有助于避免在每次渲染时都进行高开销的计算

传入useMemo的函数会在渲染期间执行。请不要再这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于useEffect的使用范畴,而不是useMemo

如果没有提供依赖项数组,useMemo在每次渲染时都会计算新的值

可以把useMemo作为性能优化的手段,但不要把它当成语义上的保证。将来React可能会选择“遗忘”以前的一些memoized值,并在下次渲染时重新计算它们,比如为离屏组件释放內存。先编写在没有useMemo的情况下也可以执行的代码 —— 之后再在你的代码中添加useMemo,以达到优化性能的目的。

Hooks

  • useState

useState是用于声明一个状态变量的,用于为函数组件引入状态
useState只接收一个参数,这个参数可以是数字、字符串、对象等任意值,用于初始化声明的状态变量。也可以是一个返回初始值的函数,最好是函数,可以在渲染时减少不必要的计算
返回一个长度为2的读写数组,数组的第一项是定义的状态变量本身,第二项是一个用来更新该状态变量的函数,约定是set前缀加上状态的变量名
useState Hook中返回的setState并不会帮我们自动合并对象状态的属性
useState中接收的对象参数如果地址没变的话会被React认为没有改变,因此不会引起视图的更新

  • useReduser

useReducer是useState的升级版。在useState中返回的接口中,我们只能传递最终的结果,在setN的内部也只是简单的赋值操作
创建初始状态值initialState
创建包含所有操作的reducer(state,action)函数,每种操作类型均返回新的state值
根据initialState和reducer使用const [ state, dispatch ] = useReducer(reducer,initialState)得到读写API
调用接口,传递的参数均挂在action对象上

  • useContext

context是上下文,上下文是局部的全局变量,这个局部的范围由开发者自己定义

  • useEffect

effect是副作用的意思,对环境的改变就是副作用。副作用是函数式编程里的一个概念
在React中,useEffect就是在每次render后执行的操作,相当于afterRender,接收的第一个参数是回调函数,第二个参数是回调时机。可用在函数组件中模拟生命周期。
如果同时出现多个useEffect,会按出现顺序依次执行

  • useLayoutEffect

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

useRef Hook是用来定义一个组件在不断render时保持不变的变量
组件每次render后都会返回一个虚拟DOM,组件内对应的变量都只属于那个时刻的虚拟DOM。
useRef Hook提供了创建贯穿整个虚拟DOM更新历史的属于这个组件的局部的全局变量
为了确保每次render后使用useRef获得的变量都能是之前的同一个变量,只能使用引用做到,因此,useRef就将这个局部的全局变量的值存储到了一个对象中,属性名为current
useRef的current变化时不会自动render
useRef可以将创建的Refs对象通过ref属性的方式引用到DOM节点或者React实例

  • useCallback

将某个函数“放入到react底层原型链上,并返回该函数的索引”,而useMemo是将某个函数返回值“放入到react底层原型链上,并返回该返回值的索引”。一个是针对函数,一个是针对函数返回值

  • uselmperativeHandle

uselmperativeHandle可以让父组件获取并执行子组件内某些自定义函数(方法)。本质上其实是子组件将自己内部的函数(方法)通过uselmperaativeHandle添加到父组件中useRef定义的对象中

  • useMemo

useMemo可以将某些函数的计算结果(返回值)挂载到react底层原型链上,并返回该函数返回值的索引。当组件重新渲染时,如果useMemo依赖的数据变量未发生变化,那么直接使用原型链上保存的该函数计算结果,跳过本次无异议的重新计算,达到提高组件性能的目的

Component和Purecomponent区别

Component没有直接实现shouldComponentUpdate这个方法;但是PureComponent通过浅层的Porps和state的对比,内部实现了这个生命周期函数
PureComponent会跳过整个组件子树的props更新,要确保全部的子组件也是pure形式
Component中需要手动执行的shouldComponentUpdate函数,在PureComponent中已经自动完成了(自动浅对比)
PureComponent不仅会影响本身,而且会影响子组件,所以PureComponent最好用在数据展示组件中
PureComponent如果是复杂数据类型,这里会造成错误的提示(setState浅复制更新,但是界面不会重新渲染)

hooks相对于class的优化

  • 类组件缺点一:复杂且不容易理解的“this”

Hooks解决方式:函数组件和普通JS函数非常相似,在普通JS函数中定义的变量、方法都可以不适用“this”,而直接适用该变量或函数,因为不需要去关心“this”了

  • 类组件缺点二:组件数据状态逻辑不能重用

Hooks解决方式:通过自定义Hook,可以将数据状态逻辑从组件中抽离出去,这样同一个Hook可以被多个组件使用,解决组件数据状态逻辑并不能重用的问题

  • 类组件缺点三:组件之间传值过程复杂,复杂场景下代码难以阻止在一起

Hooks解决方式:通过React内置的useState()函数,可以将不同数据分别从“this.state”中独立拆分出去。降低数据复杂度和可维护性,同时解决类组件缺点中“内部state数据只能是整体,无法被拆分更细”的问题

通过React内置的useEffect()函数,将componentDidMount、componentDidUpdate、componentWillUncount三个生命周期函数通过Hook(钩子)关联成1个处理函数,解决事件订阅分散在多个生命周期函数的问题

hooks父组件怎么调用子组件的方法

父组件使用useRef创建一个ref传入子组件
子组件需要使用useImperativeHandle暴露ref自定义的实例值给父组件。这个需要用forwardRef包裹着。

react通过什么方法修改参数

类组件修改数据的方法是通过setState
setState的修改方法有两种,而且它是异步的
函数组件修改方式通过自定义方法。需要通过useState,hooks

react native

React native基于JavaScript开发的一个可以开发原生app的集成框架,它兼容开发IOS和Android,能够实现一套代码,两个系统都能使用,方便维护,相比web前端的react,react-native更好的提供了一些调用手机硬件的API,可以更好的开发移动端,现在react-native它的生态环境也是越来越好,基本上可以完全实现原生开发
但是现在很多的应用还是用它来套壳(原生+web前端),用它来做有些路由,和框架的搭建,然后里面内容来使用前端的react来实现,这样一来让维护更方便,开发更便捷

redux的实现原理

redux它是一个单独的状态管理工具,它是一个数据集中管理的方案,简单的说,就是将公用的数据,放在redux里面进行存储,修改的时候也是利用redux提供的方法来修改,让框架使用的数据的时候更方便,维护起来更容易,redux提供了以下核心内容

  • store

store是redux的核心内容,整个redux的仓库,所有的应用方法都是由store提供

  • createStore

createStore用于创建store,方法里面有三哥参数,有reducer,有中间件,还有初始值,最重要的就是reducer函数,它提供了整个数据管理的逻辑

  • reducer(state,action)

reducer函数相当于数据加工厂,初始的数据,修改数据的逻辑都统统的在这里完成,它让我们整个的数据走向更完整,维护更方便

  • action

action本质是一个对象,它来告诉redux要执行什么任务

  • state

state它就是我们需要存储的redux数据,所有的数据都将要在这里面存储

  • store.getState()

它就是用来获取数据的,每次修改前后的数据都可以用store.getState()来修改

  • store.dispatch(action)

用户通过dispatch触发要执行的任务,这个就是触发动作,然后reducer函数会执行,然后进行数据加工

  • store.subscribe(callback)

会自动的监听state,一旦有state发生改变,store.subscribe就回执行,利用它可以用来更新视图

react的render什么时候渲染

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的依赖为引用类型如何处理

useEffect的依赖为引用类型的时候,可能会导致监听不触发,原因就是监听的同一个地址的时候,对象本身地址没变,所以监听的结果就是任务数据并没有改变从而不直接调用
解决方案

1.如果是数据是对象的话,可以监听对象里面的值,值是基本类型,如果值改变了,那么可以监听执行
2.在去修改对象和数据的时候,使用深拷贝或者浅拷贝,这样地址发送改变可以监听执行
3.可以转成字符串,通过JSON.stringify(),监听字符串,这样改变也会执行

Hooks需要注意的

  • 首先要注意的就是useState里面方法是异步的,所以不要在后面连续调用,由于react方法是批量异步调用,并不是每次调用修改方法都执行,所以需要用到callback写法
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 }))
};
  • 由于useState是异步的,不要在修改后直接使用数据,可以先修改数据,判断数据,也可以利用useEffect,useMemo等等通过监听数据执行
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这个hook的使用,每一个消耗性能的内容都可以通过return来消除
useEffect(() => {
  // 逻辑1
  return () => {
    // 清楚逻辑1的副作用
  }
}, [/* 监听的值 */])
  • useRef可以获取组件的数据,也可当常量的值来使用,注意获取数据使用的时候函数组件特别需要注意,如果子组件是函数组件需要利用useImperativeHandle,forWard

原生JS

Vue

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值