React面试题
- 1. React有什么特点?
- 2. JSX
- 3.你了解 Virtual DOM 吗?解释一下它的工作原理。
- 4. 为什么浏览器无法读取JSX?
- 5. 如何将两个或多个组件嵌入到一个组件中?
- 6. state 和 props有什么区别?
- 7.详细解释 React 组件的生命周期方法。
- 8. React中的合成事件(SyntheticEvent)是什么?
- 9. React 的 refs 有什么了解?
- 10. 你对受控组件和非受控组件了解多少?
- 11. 什么是高阶组件(HOC)?
- 12. 你能用HOC做什么?
- 13. 什么是纯组件?
- 14. React 中 key 的重要性是什么?
- 15. 什么是Redux?
- 16. Redux遵循的三个原则是什么?
- 17. 列出 Redux 的组件。
- 18.什么情况下需要使用redux
- 19.redux的三个核心概念
- 20. redux中的reducer为什么要使用纯函数
- 21. redux 有什么缺点
- 22. 当你调用 setState 的时候,发生了什么事?
- 23.类组件和函数组件之间有什么区别?
- 24. setState 和 replaceState 的区别
- 25. 调用 super(props) 的目的是什么
- 26.在 React 当中 Element 和 Component 有何区别?
- 27. 什么是路由?
- 28. Switch和Redirect的使用
- 29. BrowserRouter与HashRouter的区别
- 30. 路由的使用两种模式如何配置?
1. React有什么特点?
它遵循单向数据流或数据绑定。
2. JSX
1、jsx是JavaScript的一种语法扩展,它跟模板语言很接近,但是它充分具备JavaScript的能力。
2、Facebook公司给JSX的定位是JavaScript的扩展(直接决定了浏览器并不会像天然JavaScript一样地支持JSX,需要通过babel转译)
3、JSX会被babel编译为:React.createElement(),React.createElement()将返回一个叫作“ReactElement”的JS对象。(最终会转化为生成虚拟DOM 的js代码,虚拟DOM是描述DOM结构的对象)
认识Babel:是一个工具链,主要用于将ECMAScript 2015+版本的代码转换为向后兼容的JavaScript的语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
render(){
return(
<div>
<h1> Hello World from Edureka!!</h1>
</div>
);
}
3.你了解 Virtual DOM 吗?解释一下它的工作原理。
Virtual DOM 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本。它是一个节点树,它将元素、它们的属性和内容作为对象及其属性。 React 的渲染函数从 React 组件中创建一个节点树。然后它响应数据模型中的变化来更新该树,该变化是由用户或系统完成的各种动作引起的。
Virtual DOM 工作过程有三个简单的步骤。
- 每当底层数据发生改变时,整个 UI 都将在 Virtual DOM 描述中重新渲染。
- 然后计算之前 DOM 表示与新表示的之间的差异。
- 完成计算后,将只用实际更改的内容更新 real DOM。
4. 为什么浏览器无法读取JSX?
浏览器只能处理 JavaScript 对象,而不能读取常规 JavaScript 对象中的 JSX。所以为了使浏览器能够读取JSX,首先,需要用像 Babel 这样的 JSX 转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器。
5. 如何将两个或多个组件嵌入到一个组件中?
1.创建函数式或类似组件
2.在render函数中嵌入组件标签
3.执行了ReactDOM.render,渲染组件到页面
函数式组件:
(1)React解析组件标签,找到了组件。
(2)发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中。
类似组件:
(1)React解析组件标签,找到组件。
(2)发现组件是使用类定义的,随后new出来该类的实例,并通过该实例调用到原型上的render方法。
(3)将render返回的虚拟DOM转为真实DOM,随后呈现在页面中。
如下:
class MyComponent extends React.Component{
render(){
return(
<div>
<h1>Hello</h1>
<Header/>
</div>
);
}
}
class Header extends React.Component{
render(){
return
<h1>Header Component</h1>
};
}
ReactDOM.render(
<MyComponent/>, document.getElementById('content')
);
6. state 和 props有什么区别?
state 和 props都是普通的JavaScript对象。尽管它们两者都具有影响渲染输出的信息,但它们在组件方面的功能不同。即
- props 是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的props 来重新渲染子组件,否则子组件的 props 以及展现形式不会改变。
- state 的主要作用是用于组件保存、控制以及修改自己的状态,它只能在constructor 中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的 this.setState 来修改,修改 state 属性会导致组件的重新渲染。
7.详细解释 React 组件的生命周期方法。
—重要的勾子:
1.render:初始化渲染或更新渲染调用
2.componentDidMount:初次完成渲染调用
3.componentWillUnmount:卸载组件
—shouldComponentUpdate**()**:
根据特定条件返回 true 或 false。根据返回状态判断是否重新渲染组件
—即将废弃的勾子:
1.componentWillMount:仅在第一次渲染前执行
2.componentWillReceiveProps: 当从父类接收到 props 并且在调用另一个渲染器之前调用
3.componentWillUpdate:在渲染之前执行
注意:ajax请求在componentDidMount执行。在componentWillMount调用setState方法不会触发组件重新渲染,而且若是未设置初始状态,用户体验也不好。
8. React中的合成事件(SyntheticEvent)是什么?
React根据W3C规范定义了每个事件处理函数的参数,即合成事件。
事件处理程序将传递SyntheticEvent的实例,这是一个跨浏览器原生事件包装器。它具有与浏览器原生事件相同的接口,包括stopPropagation()和preventDefault(),在所有浏览器中它们工作方式都相同。
React合成的SyntheticEvent采用了事件池,这样做可以大大节省内存,而不会频繁的创建和销毁事件对象。
另外,不管在什么浏览器环境下,浏览器会将该事件类型统一创建为合成事件,从而达到了浏览器兼容的目的。
9. React 的 refs 有什么了解?
有些场景需要获取某一个真实的DOM元素来交互,比如文本框的聚焦、触发强制动画、与第三方 DOM 库集成等。
10. 你对受控组件和非受控组件了解多少?
受控组件:在React中,可变状态通常保存在组件的状态属性中,并且只能使用setState() 更新,而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。
非受控组件:表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用ref从DOM获取表单值)
11. 什么是高阶组件(HOC)?
高阶组件(high-order component)类似于高阶函数,接收 React 组件作为输入,输出一个新的 React 组件。高阶组件让代码更具有复用性、逻辑性与抽象特征。可以对 render 方法作劫持,也可以控制 props 与 state。
12. 你能用HOC做什么?
高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最常见的可能是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。
13. 什么是纯组件?
纯(Pure) 组件是可以编写的最简单、最快的组件。它们可以替换任何只有 render() 的组件。这些组件增强了代码的简单性和应用的性能。
14. React 中 key 的重要性是什么?
key 用于识别唯一的 Virtual DOM 元素及其驱动 UI 的相应数据。它们通过回收 DOM 中当前所有的元素来帮助 React
优化渲染。这些 key 必须是唯一的数字或字符串,React 只是重新排序元素而不是重新渲染它们。这可以提高应用程序的性能。
15. 什么是Redux?
1.redux是一个专门用于做状态管理的JS库(不是react插件库)。
2.它可以用在react, angular, vue等项目中, 但基本与react配合使用。
3.作用: 集中式管理react应用中多个组件共享的状态。
16. Redux遵循的三个原则是什么?
(1)单一数据源:
使用 “Store” 将程序的整个状态存储在同一个地方。单一状态树可以更容易地跟踪随时间的变化,并调试或检查应用程序。
(2)状态是只读的:
改变状态的唯一方法是去触发一个动作。动作是描述变化的普通 JS 对象。就像 state 是数据的最小表示一样,该操作是对数据更改的最小表示。
(3)使用纯函数进行更改:
为了指定状态树如何通过操作进行转换,你需要纯函数。纯函数是一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用
17. 列出 Redux 的组件。
Redux 由以下组件组成:
Action – 这是一个用来描述发生了什么事情的对象。
Reducer – 这是一个确定状态将如何变化的地方。
Store –整个程序的状态/对象树保存在Store中。
View – 只显示 Store 提供的数据。
18.什么情况下需要使用redux
1.某个组件的状态,需要让其他组件可以随时拿到(共享)。
2.一个组件需要改变另一个组件的状态(通信)。
3.总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
19.redux的三个核心概念
action:
1.动作的对象
2.包含2个属性 type:标识属性, 值为字符串, 唯一, 必要属性 data:数据属性, 值类型任意, 可选属性
3.例子:{ type: ‘ADD_STUDENT’,data:{name: ‘tom’,age:18} }
reducer:
1.用于初始化状态、加工状态。
2.加工时,根据旧的state和action, 产生新的state的纯函数。
store:
1.将state、action、reducer联系在一起的对象
2.如何得到此对象?
1)import {createStore} from ‘redux’
2)import reducer from ‘./reducers’
3)const store = createStore(reducer)
3.此对象的功能?
1)getState(): 得到state
2)dispatch(action): 分发action, 触发reducer调用, 产生新的state
3)subscribe(listener): 注册监听, 当产生了新的state时, 自动调用
20. redux中的reducer为什么要使用纯函数
若入参的state被改写,redux就监测不到state对象的变化,就不会更新视图
const initState = [{id:'001',name:'tom',age:18}]
export default function personReducer(preState=initState,action){
const {type,data} = action
switch (type) {
case 'addPerson':
//这样会导致preState被改写了,personReducer就不是纯函数了。
preState.unshift(data)
return preState
default:
return preState
}
}
正确写法
const initState = [{id:'001',name:'tom',age:18}]
export default function personReducer(preState=initState,action){
const {type,data} = action
switch (type) {
case 'addPerson':
return [data,...preState]
default:
return preState
}
}
21. redux 有什么缺点
一个组件所需要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取。
当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,可能会有效率影响,或者需要写复杂的
shouldComponentUpdate 进行判断。
22. 当你调用 setState 的时候,发生了什么事?
将传递给 setState 的对象合并到组件的当前状态,这将启动一个和解的过程,构建一个新的 react 元素树,与上一个元素树进行对比(diff ),将实际更改的内容更新 real DOM,从而进行最小化的重渲染。
23.类组件和函数组件之间有什么区别?
类组件( Class components )
类组件比函数式组件多了更多的特性,调用ReactDOM.render()时,内部会执行new Welcome(),所以可以通过this拥有组件自生的一些方法和数据,比如 state、生命周期、ref。
class Welcome extends React.Component {
render() {
return (
<h1>Welcome { this.props.name }</h1>
);
}
}
ReactDOM.render(<Welcome name='react' />, document.getElementById('root'));
函数组件(functional component)
函数组件接收一个单一的 props 对象并返回了一个React元素
function Welcome (props) { return <h1>Welcome {props.name}</h1> }
ReactDOM.render(<Welcome name='react' />,
document.getElementById('root'));
区别
1.函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。
2React 16.8.0以下版本.组件具有状态( state )或 生命周期方法,请使用 Class 组件
3.React 16.8.0版本增加的新语法Hook, 可以使用它在函数组件中使用 state(React.useState()
)、ref(React.useRef()
)、生命周期方法(React.useEffect()
)
24. setState 和 replaceState 的区别
setState 是修改其中的部分状态,相当于 Object.assign,只是覆盖, 不会减少原来的状态
replaceState 是完全替换原来的状态,相当于赋值,将原来的 state 替换为另一个对象,如果新状态属性减少,那么 state 中就没有这个状态了
25. 调用 super(props) 的目的是什么
在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用
super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props。
26.在 React 当中 Element 和 Component 有何区别?
React Element 是描述屏幕上所见内容的数据结构,是对于 UI 的对象表述。 典型的 React Element 就是利用 JSX构建的声明式代码片然后被转化为 createElement 的调用组合。
27. 什么是路由?
- 一个路由就是一个映射关系(key:value)
- key为路径, value可能是function或component
路由分类
1.后端路由: 1)理解: value是function, 用来处理客户端提交的请求。 2)注册路由: router.get(path, function(req, res)) 3)工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由,
调用路由中的函数来处理请求, 返回响应数据
2.前端路由:- 浏览器端路由,value是component,用于展示页面内容。
- 注册路由:
<Route path="/test" component={Test}>
- 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
28. Switch和Redirect的使用
Switch
1.通常情况下,path和component是一一对应的关系。
2.Switch可以提高路由匹配效率(单一匹配)。Redirect
一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
<Switch>
<Route path="/about" component={About}/>
<Route path="/home" component={Home}/>
<Redirect to="/about"/>
</Switch>
29. BrowserRouter与HashRouter的区别
- 底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。- path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
HashRouter的路径包含#,例如:localhost:3000/#/demo/test- 刷新后对路由state参数的影响
(1).BrowserRouter没有任何影响,因为state保存在history对象中。
(2).HashRouter刷新后会导致路由state参数的丢失!!!- 备注:HashRouter可以用于解决一些路径错误相关的问题。
30. 路由的使用两种模式如何配置?
React : <App>
的最外侧包裹了一个 <BrowserRouter>
或<HashRouter>
Vue : Vue默认hash模式,在mode可以改成history模式