当前位置: 首页 > Web前端 > HTML

社招前端react面试必做题

时间:2023-03-27 22:41:09 HTML

什么是JSXjsx是javascriptML的缩写,react使用的一种文件,利用了JavaScript的表现力和类似HTML的模板语法,使得HTML文件非常容易理解。该文件可以使应用程序非常可靠并提高其性能。定义虚拟DOM时,定义虚拟DOM时不需要写引号。在jsx中写标签的类名时需要使用{}。当className替换类内联样式时,style={{key:value}}标签必须关闭。如果是小写字母,将jsx转为html中的同名元素。如果html中没有这个标签对应的同名元素就会报错。如果是大写字母,react会渲染对应的组件。如果没有定义组件,会报错。当根据数据遍历生成标签时,必须为标签设置单独的key。否则会报错。当你要配置webpack或babel预设时,什么原因会提示你离开create-react-app依赖。跨层组件如何通信?父组件与子组件的子组件通信,与更深层的子组件通信:使用props,使用中间组件逐层传递,但如果父组件结构较深,则每一个中间组件必须传递props,增加了复杂度,而且中间组件本身不需要这些props。使用context,context相当于一个大容器,可以将要交流的内容放在这个容器中,这样无论嵌套多深,都可以随意访问,也可以跨多个层的全局数据使用上下文实现。//context方法实现了跨层级的组件通信//context的目的是共享对组件树来说是“全局”的数据constBatteryContext=createContext();//子组件subcomponentclassGrandChildextendsComponent{render(){return({color=>Iamred:{color}})}}//子组件constChild=()=>{return()}//父组件类ParentextendsComponent{state={color:"red"}render(){const{color}=this.statereturn()}}什么是状态提升使用react经常会遇到几个组件需要共享状态数据的情况。在这种情况下,我们最好将这部分共享状态提升到离它们最近的父组件中进行管理。让我们看看它是如何工作的。importReactfrom'react'classChild_1extendsReact.Component{constructor(props){super(props)}render(){return(

{this.props.value+2}

)}}classChild_2扩展React.Component{constructor(props){super(props)}render(){return(

{this.props.value+1}

)}}classThreeextendsReact.Component{constructor(props){super(props)this.state={txt:"牛逼"}this.handleChange=this.handleChange.bind(this)}handleChange(e){this.setState({txt:e.target.value})}render(){return(

{this.state.txt}

)}}exportdefault三时调用setState时会发生什么?**当调用setState时,React做的第一件事是将传递给setState的对象合并到组件的当前状态中,这会启动一个称为协调的过程。协调的最终目标是根据这个新状态以最有效的方式更新DOM。为此,React将构建一个新的React虚拟DOM树(将其视为页面DOM元素的对象表示)。一旦你有了这棵DOM树,React就会将这棵新树与之前的虚拟DOM树进行比较,以确定DOM如何响应新状态而发生变化。通过这样做,React可以准确地知道发生了什么变化,并且可以在知道发生了什么变化后在绝对必要时通过更新DOM来最小化操作DOM所占用的空间。React中的Portal是什么?门户提供了一种很好的方式来将子节点呈现给DOM节点而不是父组件。第一个参数(child)是任何可渲染的React子元素,例如元素、字符串或片段。第二个参数(容器)是一个DOM元素。ReactDOM.createPortal(child,container)参考前端高级面试题详解React组件中如何做事件代理?它的原理是什么?React基于VirtualDOM实现了一个SyntheticEvent层(合成事件层)。定义的事件处理器会接收一个合成事件对象的实例,该对象符合W3C标准,与浏览器原生事件具有相同的接口,支持冒泡机制,所有事件自动绑定到最外层。在React底层,对于合成事件主要做了两件事:事件委托:React会将所有的事件绑定到结构的最外层,使用一个统一的事件监听器,它维护一个映射来保存所有组件内部的事件监听和处理功能。自动绑定:在React组件中,每个方法的上下文都会指向组件的实例,即this自动绑定到当前组件。你理解这句话“在React中,一切都是组件”。组件是React应用程序UI的构建块。这些组件将整个UI划分为独立且可重用的小部分。每个组件相互独立,不会影响UI的其余部分。在使用jsx的组件中看不到react,为什么还要引入react?本质上,JSX是React.createElement(component,props,...children)方法的语法糖。在React17之前,如果你使用JSX,你实际上是在使用React,babel会将组件转换为CreateElement形式。React17之后就不需要导入了,因为babel可以自动帮我们导入react。如何比较diff算法?仅用于同级比较,跨级dom不会被复用。不同类型的节点生成的dom树是不一样的。此时会直接销毁旧节点和后代节点,新创建的节点可以使用key对元素进行diff的过程提供线索以供重用。Single-nodediff单点diff有以下几种情况:相同的key和type表示如果key不同则节点可以复用,直接标记为删除节点,然后新建的节点有相同的key和不同的类型,节点和兄弟节点被标记为删除。,然后新建一个节点ReactHooks正常开发中需要注意的问题和原因(1)不要在循环、条件或嵌套函数中调用Hooks,必须始终在React函数的顶层使用Hooks这是因为React需要利用调用顺序来正确更新相应的状态,并调用相应的钩子函数。Hook一旦在循环或条件分支语句中被调用,很容易造成调用顺序不一致,造成不可预知的后果。(2)使用useState时,使用push、pop、splice等方式直接改变数组对象的坑。使用push直接改变数组是获取不到新值的。应该使用析构方法,但是在类中不会出现这个问题。代码示例:functionIndicatorfilter(){let[num,setNums]=useState([0,1,2,3])consttest=()=>{//这里的陷阱是直接使用push更新num//setNums(num)不能更新num//必须使用num=[...num,1]num.push(1)//num=[...num,1]setNums(num)}return(测试
{num.map((item,index)=>({item}
))}
)}classIndicatorfilterextendsReact.Component{constructor(props:any){super(props)this.state={nums:[1,2,3]}this.test=this.test.bind(this)}test(){//类采用相同的方法没问题this.state.nums.push(1)this.setState({nums:this.state.nums})}render(){let{nums}=this.statereturn(
test
{nums.map((item:any,index:number)=>({item}
))}
)}}(3)useState设置状态时,只在第一次生效,后面需要更新状态。它必须通过useEffectTableDeail是一个公共组件。在调用它的父组件中,我们通过set改变columns的值,认为传递给TableDeail的column是最新的值,所以tabColumn每次也是最新的值,但是实际的tabColumn是初始值,不会随着列的更新而更新:constTableDeail=({columns,}:TableData)=>{const[tabColumn,setTabColumn]=useState(columns)}//正确的做法是通过useEffect改变这个值constTableDeail=({columns,}:TableData)=>{const[tabColumn,setTabColumn]=useState(columns)useEffect(()=>{setTabColumn(columns)},[columns])}(4)parent时用好useCallbackcomponent传递给子组件的事件处理器,如果我们没有任何参数变化,我们可以选择useMemo,但是每次父组件渲染子组件,即使没有变化也会渲染一次。(5)不要滥用useContext可以使用基于useContext封装的状态管理工具。React的性能优化方法有哪些?类组件中的优化方法使用纯组件PureComponent作为基类。使用React.memo高阶函数包装组件。使用shouldComponentUpdate生命周期函数来自定义渲染逻辑。方法组件中的优化使用useMemo。使用回调。其他方式,当列表需要经常变化时,使用唯一id作为键,而不是数组下标。需要时通过改变CSS样式来隐藏显示的组件,而不是通过条件判断来显示和隐藏组件。使用Suspense和lazy进行延迟加载,例如:importReact,{lazy,Suspense}from"react";导出默认类CallingLazyComponentsextendsReact.Component{render(){varComponentToLazyLoad=null;if(this.props.name=="Mayank"){ComponentToLazyLoad=lazy(()=>import("./mayankComponent"));}elseif(this.props.name=="Anshul"){ComponentToLazyLoad=lazy(()=>import("./anshulComponent"));}return(

这是基本用户:{this.state.name}

Loading...
}>)}}React老生命周期函数初始化阶段getDefaultProps:获取实例的默认属性getInitialState:获取各个实例的初始化状态componentWillMount:组件即将加载并渲染到页面render:组件在这里生成一个虚拟DOM节点componentDidMount:组件加载后实际运行componentWillReceiveProps:当组件即将接收属性时调用shouldComponentUpdate:组件接收新属性或新状态state(可返回false,接收数据后不更新,阻止render调用,后续函数不会继续执行)componentWillUpdate:组件即将更新,不能修改属性和状态render:组件重绘组件已被更新销毁componentWillUnmount:组件即将被销毁ordercomponent:如果一个函数接受一个或多个组件作为参数,并返回一个组件,则可以称为高阶组件。React中的高阶组件React中的高阶组件主要有两种形式:属性代理和反向继承。属性代理Proxy操作props来提取状态并通过ref访问组件实例。用其他元素包裹传入的组件。WrappedComponent反向继承会发现propertyproxy和反向继承的实现有些类似,都是返回一个被继承的。父类的子类,除了属性代理继承React.Component,反向继承继承传入的组件WrappedComponent。反向继承可以用来做什么:1.操作高阶组件中的状态可以读取、编辑和删除WrappedComponent组件实例中的状态。甚至可以添加更多的状态项,但不推荐这样做,因为这可能会使状态难以维护和管理。functionwithLogging(WrappedComponent){returnclassextendsWrappedComponent{render(){return(
;

;DebuggerComponentLogging...

;

;state:

;

;{JSON.stringify(this.state,null,4)}
;

props:

;

{JSON.stringify(this.props,null,4)}
;{super.render()}
;);}};}2。RenderHighjacking条件渲染使用props.isLoading的条件来确定渲染哪个组件。修改render()输出的React元素树组件的通信方式。父组件与子组件通信:父组件可以通过传递props与子组件通信子组件与父组件通信:props+回调的方式,父组件将props传递给子组件进行通信。这个props是一个作用域是父组件本身的函数。子组件调用该函数,将子组件要传递的信息作为参数传递。与父组件作用域内的兄弟组件通信:找到两个兄弟节点的共同父节点,并结合以上两种方法从父节点转发信息进行通信跨层通信:上下文旨在共享那些对于组件树是“全局”数据,例如当前认证的用户、主题或首选语言,发布-订阅模型非常适合通过Context通信跨越多个层的全局数据:发布者发布事件,订阅者监听事件并响应.我们可以通过引入事件模块来进行通信。全局状态管理工具:与Redux或Mobx等全局状态管理工具通信,会在脑海中维护一个全局状态Store,根据不同的事件生成新的状态你在React中用过getDefaultProps吗?它有什么作用?通过实现组件的getDefaultProps,为属性设置默认值(ES5写法):varShowTitle=React.createClass({getDefaultProps:function(){return{title:"React"}},render:function(){return

{this.props.title}

}});描述一下Flux和MVC?传统的MVC模式对于分离数据(Model)、UI(View和逻辑(Controller))效果很好,但是MVC架构通常存在两个主要问题:数据流不够清晰:跨View发生的级联更新经常导致事件混乱难以调试的网络。缺乏数据完整性:模型数据可能在任何地方发生变异,在整个UI中产生不可预测的结果。使用Flux模式的复杂UI不再受到级联更新的影响,任何给定的React组件都能够重建其状态基于商店提供的数据。Flux模式还通过限制对共享数据的直接访问来加强数据完整性。什么是螺旋钻以及如何避免?在构建React应用程序时,在多个级别嵌套组件以使用另一个嵌套组件提供的数据。最简单的方法是从每个组件向下传递一个prop,从源组件到深层嵌套的组件。这称为螺旋桨钻井。螺旋钻井的主要缺点是不需要数据的组件变得不必要地复杂且难以维护。为了避免propdrilling,一种常见的方法是使用ReactContext。通过定义提供数据的Provider组件,并允许嵌套组件通过Consumer组件或useContextHook使用context数据。如何更新redux用户发起操作后,dispatch发送一个action,根据类型触发对应的reducer。reducer是一个纯函数,它接收旧状态和动作并返回新状态。通过subscribe(listener)侦听器分发更新。什么是受控组件?在HTML中,