React面试题
]kk前端全部面试题
86张脑图,一口气看完 React 🎉 - 掘金
https://blog.csdn.net/qq_40055200/article/details/104637574
React面试题
创建一个react项目
1.全局安装create-react-app
npm install -g create-react-app
2.创建项目
create-react-app myapp
3.局部安装,可以直接用npx
npx create-react-app myapp
4.进入文件夹
cd myapp
5.启用项目
npm start(开发模式下运行)
npm test(测试环境运行)
npm run build(打包为生产模式)
6.显示配置文件:不可逆的,只要显示了就没有任何方法再隐藏回去
npm run eject
这里需要等待一段时间,实际上会安装三个东西
react:react的顶级库
react-dom:因为react有很多的运行环境,比如app端的react-native,我们要在web上运行就使用react-dom
react-script:包含运行和打包react应用程序的所有脚本及配置
1.React是什么?(用来构造用户界面的JS库)
2.React有什么特点?(react的主要功能有哪些?)
它用于虚拟DOM,组件化设计模式,声明式代码,单向数据流,使用jsx描述信息等特点
3.什么是虚拟DOM?
用于构建虚拟的HTML的DOM
虚拟DOM可以看做是一棵模拟DOM树的js对象树。例如:
var element = {
element: 'ul',
props: {
id:"ulist"
},
children: [
{ element: 'li', props: { id:"first" }, children: ['这是第一个List元素'] },
{ element: 'li', props: { id:"second" }, children: ['这是第二个List元素'] }
]
}
4.为什么要使用虚拟DOM?
传统的数据只要发生变化,就会引起DOM重新渲染。虚拟DOM的目的是将所有操作累加起来,统计计算出所有的变化后,统一更新一次DOM。
5.什么是组件化设计模式?
可复用的代码可以抽成组件共同使用(UI,方法等)
6.声明式代码(编程)思想:
就是说明下你的目的,然后具体不说明怎么去做。
举例子:去酒吧告诉服务员你要一杯鸡尾酒,服务员把做好的鸡尾酒给你,并没有说做的过程是怎样的
const toLowerCase = arr = arr.map(
value => value.toLowerCase();
)
7.还有其他的编程方式吗?
命令式编程:就是描述代码如何工作,告诉计算机一步步的执行,先做什么后做什么。
举例子:去酒吧点一杯酒,指挥服务员
从架子上取下一个玻璃杯
把杯子放在酒桶前
打开酒桶开关,直到酒杯杯满
把做好的鸡尾酒递给顾客
const toLowerCase = arr => {
const res = [];
for (let i = 0, len = arr.length; i < len; i++) {
res.push(arr[i].toLowerCase());
}
return res;
}
8.React事件处理的几种方法(如何创建一个事件)
import React from 'react'
class Test extends React.Component{
handleClick2(){
console.log('click2')
}
hangleClick4 = () =>{
console.log('click4')
}
render(){
return(
<button onClick={ console.log('click1')}>click1</button>
<button onClick={ this.handleClick2.bind(this)}>click2</button>
<button onClick={ () => {console.log('click3')}>click3</button>
<button onClick={ this.hangleClick4 }>click3</button>
)
}
}
export default Test
9.什么是单向数据流
数据主要从父节点传到子节点(通过props),如果父级的某个props改变了,React会重新渲染所有子节点(像瀑布的水一样,从上往下流,这个水就是组件的数据流。)
若子组件想要改版父子组件的值应该如果去做呢?
如下:event事件,子组件是不能够在自己的组件中去修改父组件的值,所以子组件中可以通过调用父组件的方法在父组件的方法中修改父组件的值
// 父组件
import React, {Component} from 'react'
import Child from './Child'
class Parent extends Component{
// 初始化
constructor(props){
super(props)
this.state = {
message: '我是从父组件传过来的'
}
}
handleUpdate = () =>{
this.setState({
message: '子组件修改父组件的值'
})
}
// 渲染
render(){
return(
<div>
<Son msg={this.state.message} event={this.handleUpdate()}/>
</div>
)
}
}
export default Parent
// 子组件
import React, {Component} from 'react'
class Child extends Component{
// 初始化
constructor(props){
super(props)
}
// 渲染
render(){
return(
{this.props.message}
<button onClick={() =>{this.props.event()}}>子组件调用父组件的方法
)
}
}
export default Child
10.什么是JSX呢?JSX代码到显示内容的转换过程
JSX就是JS的扩展语言(jsx语法= js语法+xml(html)语法)
JSX是JavaScript XML的缩写,是JavaScript的语法扩展,本质上是JavaScript对象。JSX可以很好的描述UI信息,但是浏览器无法直接读取,编译过程中会将JSX转换成JS的语法。
render(){
return(
Hello World from Edureka!!
);
}
11.react的优缺点
优点:
提高了应用性能和开发效率
使用JSX,代码可读性好
react的componentWillUnmount生命周期,能够清除相关所有事件,避免内存泄露
并不直接对DOM进行操作,引入了一个虚拟DOM的概念,安插在js和真实DOM中间,性能好,速度快
缺点:
每次 state 更改,render 函数都要生成完整的虚拟 DOM. 哪怕 state 改动很小,render函数也会完整计算一遍。如果 render 函数很复杂,这个过程就白白浪费了很多计算资源
react 缺点_不玩微博的jason2的博客-CSDN博客_react缺点
12.VUE与React两个框架的区别对比
相似之处:
用于创建UI的js库
使用起来轻快便捷
都用了虚拟DOM
都是基于组件的架构
不同点 :
vue使用的html模板;react使用的是js
vue有双向绑定语法
vue增加了语法糖computed和watch等,react需要自己写逻辑来实现
react用了jsx语法
react整体思路是编程式,推荐组件化,数据不变,单向数据流;vue数据可变,双向绑定,声明式的写法
react使用的是js
13.React的工作原理
React会创建一个虚拟的DOM。当一个组件的状态改变时,React首先会通过“diffing"算法来标记虚拟DOM中的改变,第二步是调节,会用diff的结果来更新DOM.
15.Real DOM和Virtual DOM
React不直接操作DOM,而是实现了Virtual DOM,组件DOM映射到这个虚拟DOM上。React在虚拟DOM上实现了differ算法,当要重新渲染组件的时候,会通过diff寻找到要变更的DOM节点,再把这个修改更新到浏览器实际的DOM节点上。
17.为什么虚拟DOM会提高性能
虚拟DOM相当于在JS和真实DOM中间加了一个缓存,利用diff减少了没有必要的操作,从而提高性能,本质上是JS对象。
虚拟DOM是映射真实DOM的js对象数据结构
采用虚拟DOM,避免直接操作真实的DOM,提供性能
当状态更新时,重新渲染新的虚拟DOM,采用diff算法对比新旧DOM,进行更新
18.阻止React的默认行为
e.preventDefault(),e是第三方提供的一个合成事件(注意:不能用return)
class App extends React.component{
constructor(props){
super(props);
this.state = {
}
}
hander(e){
e.preventDefault()
}
render(){
return <button onClick={ this.hander.bind(this) }>阻止事件
}
}
19.向事件处理程序传递参数
例如删除当前行的ID
<button onClick={(e) => this.delete(e,id)}>Delete Row
20.React中key作用是什么?
作用(目的):key是用于追踪那些列表中元素被修改,删除或者被添加的辅助标识。在diff算法中,key用来判断该元素节点是被 移动过来的还是新创建元素,减少不必要的元素重复渲染。
22.React中diff算法
diff算法的作用是用来计算出Virtual DOM中被改变的部分,然后针对该部分进行原生DOM操作,而不用重新渲染整个页面。
深入理解React虚拟DOM - 110255 - 博客园
diff算法有3种策略:
tree diff:DOM节点跨层级的移动操作特别少,可以忽略不计。
component diff:拥有相同类的两个组件生成相似的数据结构;拥有不同类的两个组件生成不同的树形结构
element diff:对于同一层级的一组子节点,通过唯一id区分
diff算法的原理
将树形结构按照层级分解,只比较同级元素
给列表结构的每个单元添加唯一的key属性,方便比较
React只会匹配相同的class的component
合并操作,调用component的setState方法的时候,React将其标记为dirty,到每一轮事件循环结束,React检查所有标记dirty的component重新渲染
选择性子树渲染。开发人员可以重新shouldComponentUpdate提高diff的性能。
23.React中Element与Component
Element是描述屏幕上课件内容的数据结构,是对UI对象的标书
Component是可以接受参数输入并且返回某个ReactElement的函数或者类
24.props和state((组件的)状态(state)和属性(props)之间有何不同)
state是数据结构,会随着事件推移发送变化,只能使用setState来改变
props是组件的属性,由父组件传递给子组件,props是不可以改变的
state是局部的,除了它所在的这个组件其它组件都无法访问
无状态组件:没有设置state的组件(无状态组件通过函数式声明来构建,2一个函数就是一个组件)
有状态组件:设置了state的组件(有状态组件通过component来构建,一个子类就是一个组件)
25.React可以用两种方法声明组件(Component),他们的区别是什么,什么情况你会选择哪一种?(React中有哪些构建组件的方式)
函数组件:首字母要大写,需要return出react元素
类组件(Class Components):首字母要大写,需要使用render方法,return出react元素
// 函数组件
function Welcome(props){
return (
hello world
) }// 类组件:es6的加入让js直接支持使用class来定义类,react创建组件的方式是使用继承,官网推荐这种
// 使用方式,使用es6标准语法来构建
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component{
render(){
return (
)
}
}
ReactDOM.render(
)
区别:
函数组件看似只是一个返回值是DOM结构的函数,其实它的背后是无状态组件的思想
函数组件中,你无法使用State,也无法使用组件的生命周期方法,这就决定了函数组件都是展开性组件,接收props,渲染DOM,而不关注其它逻辑
函数组件中没有this
函数组件更容易理解。当你看到一个函数组件时,你就知道它的功能只是接收属性,渲染页面,它不执行与UI无关的逻辑处理,它只是一个纯函数。而不用在意它返回的DOM结构有多复杂
26.React组件生命周期的阶段是什么?
React 组件的生命周期有三个不同的阶段:
初始渲染阶段:这是组件即将开始其生命之旅并进入 DOM 的阶段。
更新阶段:一旦组件被添加到 DOM,它只有在 prop 或状态发生变化时才可能更新和重新渲染。这些只发生在这个阶段。
卸载阶段:这是组件生命周期的最后阶段,组件被销毁并从 DOM 中删除。
27.简单聊聊生命周期(指出(组件)生命周期方法的不同)
constructor:在构造函数中初始化props和state
class Timer extends React.Component {
constructor(props) {
super(props)
this.state = {seconds: 0}
}
tick(){
this.setState(state =>({
seconds: state.seconds + 1
}))
}
componentDidMount() {
this.interval = setInterval(() => this.tick(),1000)
}
componentWillMount(){
clearInterval(this.interval);
}
render() {
return (
<div> Seconds: {this.state.seconds} </div>
)
}
}
componentWillMount--在组件渲染之前执行,对state进行最后的修改
render:渲染
componentDidMount-- 在组件渲染之后执行
componentWillReceiveProps -- 这个周期函数作用于特定的 prop 改变导致的 state 转换
shouldComponentUpdate -- 用来做性能优化的,根据特定条件返回 true 或 false。如果你希望更新组件,请返回true 否则返回 false。默认情况下,它返回 false。
componentWillUpdate -- 数据在改变之前执行
componentDidUpdate -- 渲染发生后立即调用
componentWillUnmount -- 从 DOM 卸载组件后调用。用于清理内存空间
28.什么是单向数据流和状态提升
单向数据流:从上往下父组件将state数据流向子组件,子组件通过props取值(像瀑布的水一样,从上往下流,这个水就是组件的数据流)
状态提升:组件之间的数据交互(很多子组件想用这个状态,将这个状态提升到最上面,通过props谁用给谁)
举例子:如果两个组件都需要用到对方的状态,那么这时候就可以用到状态提升。具体做法是把两个子组件的状态写到他们的父组件中,然后父组件把状态传递给子组件的props中去,这样子组件也相当于有状态。
父组件
import React from "react"
import Child1 from "./child1"
import Child2 from "./child2"
export default class Parent extends React.Component {
constructor() {
super()
this.state = {
money: 1
}
}
changeHander(e){
this.setState({
money: e.target.value
})
}
render() {
return (
<div>
<input type="text" value={ this.state.money } onChange={this.changeHander.bind(this)} />
<p>Parent</p>
人民比: <Child1 money={this.state.money} />
美金: <Child2 money={this.state.money} />
</div>
)
}
}
子组件1
import React from "react"
export default class Child1 extends React.Component{
constructor(){
super()
this.state = {
input1: 0
}
}
componentDidMount(){
this.setState({
input1: this.props.money
})
}
changeHander(e) {
this.setState({
input1: e.target.value
})
}
render() {
return(
<div>
{ this.props.money }
<input type="text" value={ this.state.input1 } onChange={ this.changeHander.bind(this) }/>
</div>
)
}
}
子组件2
import React from "react"
export default class Child2 extends React.Component{
constructor(){
super();
this.state = {
input2: 1
}
}
componentDidMount(){
this.setState({
input2: this.props.money * 7
})
}
changeHander(e) {
this.setState({
input2: e.target.value
})
}
render() {
return(
<div>
{ this.props.money * 7}
<input type="text" value={ this.state.input2 } onChange={ this.changeHander.bind(this) }/>
</div>
)
}
}
29.调用setState之后发生了什么
setState会进行状态更新
将传入的参数对象与组件当前状态合并,然后触发所谓的调和过程,经过调和过程,根据新的state,React元素会重新构建虚拟DOM,进行diff算法对比新旧虚拟DOM树的区别,进行视图更新,而不是全部渲染。
setState 采用的任务队列机制,不会马上执行,而是加入队列,在下次事件循环是一次性执行
30.为什么建议传递给setState的参数是一个callback(回调函数)而不是一个对象(不懂--先不用背)
因为this.props和this.state的更新可能是异步的,不能依赖他们的值去计算下一个state
31.关于this绑定==组件绑定点击事件
// bind
// 1
</React.Fragment>
)
}
// 2.在构造函数中默认绑定this(推荐)
this.handleClick = this.handleClick.bind(this)
// 3.使用箭头函数来处理,handleClick点击事件的方法
<button onClick={(e) => this.handleClick(e)}>Click me
32.setState第二个参数的作用
该函数会在setState函数调用完成并且组件开始重渲染的时候被调用,我们可以用该函数来监听渲染是否完成
(在构造函数中)调用 super(props) 的目的是什么
在 super() 被调用之前,子类是不能使用 this 的,在 ES5 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props
33.什么是React 路由?
Router 用于定义多个路由,当用户定义特定的 URL 时,如果此 URL 与 Router 内定义的任何 “路由” 的路径匹配,则用户将重定向到该特定路由。
路由是根据不同的url地址展示不同的内容或页面
import React from 'react';
import { Switch, Route, BrowserRouter } from 'react-router-dom';
import Home from './views/Home'
export default class App extends React.Component{
// 初始化
constructor(props){
super(props);
this.state = {}
}
// 渲染
render(){
return(
)
}
}
- 区分Real DOM和Virtual DOM
Real DOM Virtual DOM
1.更新缓慢 1.更新更快
2.可以直接更新HTML 2.无法直接更新HTML
3.如果元素更新,则创建新DOM 3.如果元素更新,则更新JSX
4.DOM操作代价很高 4.DOM操作很简单
5.消耗的内存较多 5.很少消耗内存
35. 为什么浏览器无法读取JSX?
浏览器只能处理JavaScript对象,而不能读取常规JavaScript对象中的JSX。所以为了使浏览器能够读取JSX,首先,需要像Babel这样的JSX转换器将JSX转换为JavaScript对象,然后再传给浏览器
- 你理解“在React中,一切都是组件”这句话。
组件是React应用UI的构建块。这些组件将整个UI分成小的独立并可重用的部分。每个组件彼此独立,而不会影响UI的其余部分
- 解释 React 中 render() 的目的。
接收数据和返回展示的内容
class HelloMessage extends React.Component {
render() {
return (
Hello {this.props.name}
);
}
}
ReactDOM.render(
document.getElementById('hello-example')
);
39. 什么是 Props?
Props是React中属性的简写。它们是只读组件,必须保持纯,即不可变。它们总是再整个应用中从父组件传递到子组件。子组件永远不能将prop送回到父组件。这有助于维护单向数据流,通常用于呈现动态生成的数据
- React中的状态是什么?它是如何使用的?
状态是React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现和行为的对象。与props不同,它们是可变的,并创建动态和交互式组件。可以通过this.state()访问它们。
- 区分状态和 props
条件 State Props
1.从父组件中接收初始值 Y Y
2.父组件可以改变值 N Y
3.在组件中设置默认值 Y Y
4.在组件的内部变化 Y N
5.设置子组件的初始值 Y Y
6.在子组件的内部更改 N Y
42.如何更新组件的状态?
可以用 this.setState()更新组件的状态。
class MyComponent extends React.Component {
constructor() {
super();
this.state = {
name: 'Maxx',
id: '101'
}
}
render()
{
setTimeout(()=>{this.setState({name:'Jaeha', id:'222'})},2000)
return (
Hello {this.state.name}
Your Id is {this.state.id}
);
}
}
ReactDOM.render(
);
43.React 中的箭头函数是什么?怎么用?
箭头函数(=>)是用于编写函数表达式的简短语法。这些函数允许正确绑定组件的上下文,因为在ES6中默认下不能使用自动绑定。使用高阶函数时,箭头函数非常有用
//General way
render() {
return(
<MyInput onChange = {this.handleChange.bind(this) } />
);
}
//With Arrow Function
render() {
return(
<MyInput onChange = { (e)=>this.handleOnChange(e) } />
);
}
44.区分有状态和无状态组件。
有状态组件 无状态组件
1.在内存中存储有关组件状态变化的信息 1.计算组件的内部状态
2.有权改变状态 2. 无权改变状态
3. 包含过去、现在和未来可能的状态变化情况 3. 不包含过去,现在和未来可能发生的状态变化情况
4. 接受无状态组件状态变化要求的通知,然后将 props 发送给他们。 4.从有状态组件接收 props 并将其视为回调函数。
45. React中的事件是什么?
在 React 中,事件是对鼠标悬停、鼠标单击、按键等特定操作的触发反应。处理这些事件类似于处理 DOM 元素中的事件。但是有一些语法差异,如:
用驼峰命名法对事件命名而不是仅使用小写字母。
事件作为函数而不是字符串传递。
事件参数重包含一组特定于事件的属性。每个事件类型都包含自己的属性和行为,只能通过其事件处理程序访问。
47.React中的合成事件是什么?
合成事件是围绕浏览器原生事件充当跨浏览器包装器的对象。它们将不同浏览器的行为合并为一个 API。这样做是为了确保事件在不同浏览器中显示一致的属性。
48.你对 React 的 refs 有什么了解?
Refs 是 React 中引用的简写。它是一个有助于存储对特定的 React 元素或组件的引用的属性,它将由组件渲染配置函数返回。用于对 render() 返回的特定元素或组件的引用。当需要进行 DOM 测量或向组件添加方法时,它们会派上用场。
class ReferenceDemo extends React.Component{
display() {
const name = this.inputDemo.value;
document.getElementById('disp').innerHTML = name;
}
render() {
return(
Name: <input type="text" ref={input => this.inputDemo = input} />
Hello !!!
);
}
}
49.列出一些应该使用 Refs 的情况。
以下是应该使用 refs 的情况:
需要管理焦点、选择文本或媒体播放时(请看React-60)
触发式动画
与第三方 DOM 库集成
50.如何模块化 React 中的代码?
可以使用 export 和 import 属性来模块化代码。它们有助于在不同的文件中单独编写组件。
//ChildComponent.jsx
export default class ChildComponent extends React.Component {
render() {
return(
This is a child component
);
}
}
//ParentComponent.jsx
import ChildComponent from './childcomponent.js';
class ParentComponent extends React.Component {
render() {
return(
);
}
}
52.解释react中render()的目的
每个React组件强制要求必须有一个render().它返回一个React元素,是原生DOM组件的表示。如果需要渲染多个HTML元素,则必须将它们组合在一个封闭标记内,例如