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 (

欢迎进入react组件

)
}
}
ReactDOM.render(
,document.getElementById('root')
)

区别:

函数组件看似只是一个返回值是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(





)
}
}

  1. 区分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对象,然后再传给浏览器

  1. 你理解“在React中,一切都是组件”这句话。

组件是React应用UI的构建块。这些组件将整个UI分成小的独立并可重用的部分。每个组件彼此独立,而不会影响UI的其余部分

  1. 解释 React 中 render() 的目的。

接收数据和返回展示的内容

class HelloMessage extends React.Component {
render() {
return (


Hello {this.props.name}

);
}
}

ReactDOM.render(
,
document.getElementById('hello-example')
);
39. 什么是 Props?

Props是React中属性的简写。它们是只读组件,必须保持纯,即不可变。它们总是再整个应用中从父组件传递到子组件。子组件永远不能将prop送回到父组件。这有助于维护单向数据流,通常用于呈现动态生成的数据

  1. React中的状态是什么?它是如何使用的?

状态是React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现和行为的对象。与props不同,它们是可变的,并创建动态和交互式组件。可以通过this.state()访问它们。

  1. 区分状态和 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(
, document.getElementById('content')
);

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元素,则必须将它们组合在一个封闭标记内,例如

,,
等。此函数必须保持纯净,即必须每次调用时都返回相同的结果。

53.如何将两个或多个组件嵌入到一个组件中?

// 可以通过以下方式
class MyComponent extends React.Component{
render(){
return(


Hello




);
}
}
class Header extends React.Component{
render(){
return

Header Component


};
}
ReactDOM.render(
, document.getElementById('content')
);

54.React事件机制

点我
React并不是将click事件绑定到了div的真实DOM上,而是在document处监听了所有的事件,当事件发生并且冒泡到document处的时候,React将事件内容封装并交由真正的处理函数运行。这样的方式不仅仅减少了内存的消耗,还能在组件挂在销毁时统一订阅和移除事件。

除此之外,冒泡到document上的事件也不是原生的浏览器事件,而是由react自己实现的合成事件(SyntheticEvent)。因此如果不想要是事件冒泡的话应该调用event.preventDefault()方法,而不是调用event.stopProppagation()方法。

是怎么较少内存消耗的???

事件委派

自动绑定

在 React 组件中,每个方法的上下文都会指向该组件的实例,即自动绑定this为当前组件。但是使用 ES6 classes 或者纯函数时,需要手动实现this的绑定

渲染组件

当react元素

function Welcome(props) {
return

Hello, {props.name}


}

const element =
ReactDOM.render(
element,
document.geteElementById('root')
)
56.事件处理

// 传统的

// react

// 开关按钮
class Toggle extends React.Component{
constructor(props){
super(props)
this.state = {isToggleOn: true}

    // 为了在回调中使用this,这个绑定是必不可少的
    this.handleClick = this.handleClick.bind(this)
}

handleClick() {
    this.setState(state =>({
        isToggleOn: !state.isToggleOn
    }))
}

render() {
    return (<button onClick={this.handleClick}>
                {this.state.isToggleOn ? 'ON' : 'OFF'
            </button>)
}

}

ReactDOM.render(
,
document.getElementById('root')
)

class LoggingButton extends React.Component{
handleClick = () =>{
console.log(this)
}
render(){

}

}

57.受控组件

使React的state成为“唯一数据源”。被React以这种方式控制取值的表单输入元素叫“受控组件”。

受控组件一般用于“表单处理数据”

更新流程:

可以通过在初始state中设置表单的默认值
每当表单的值发生变化时,调用onChange事件处理器,
事件处理器通过事件对象e拿到改变后的状态,改变state;
setState触发视图更新,完成表单组件值的更新
class NameForm extends React.Component{
constructor(props){
super(props)
this.state = {value: ''}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}

handleChange(event){
    this.setState({}value: event.target.value)
}

handleSubmit(event){
    alert('提交的名字:' + this.state.value)
    event.preventDefault()
}

render(){
    return (
        <form onSubmit={this.handleSubmit}>
            <label>
                名字:
                <input type="text" value={this.state.value} onChange={this.handleChange}/>
            </label>
                <input type="submit" value="提交"/>
        </form>
    )
}

}

58.非受控组价

非受控组件,即组件的状态不受React控制的组件,例如下边这个

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class Demo1 extends Component {
render() {
return (

)
}
}

ReactDOM.render(, document.getElementById('content'))
在这个最简单的输入框组件里,我们并没有干涉input中的value展示,即用户输入的内容都会展示在上面。如果我们通过props给组件设置一个初始默认值,defaultValue属性是React内部实现的一个属性,目的类似于input的placeholder属性。

为什么在src创建子目录?

webpack只处理src的中的文件。如果不讲css和html放在src文件夹下,webpack发现不了。

react是单页面应用程序

单页面应用:

理解:单页面不需要加载整个页面,单页面就是一个页面,用路由来切换组件显示,页面只有一个index.html,不管什么组件都是在这个页面里的,最后都放在这里面了

非单页面:原来那种网站 每点个链接 都是整个页面刷新 有的登录都是刷新,原来网站会有很多html文件

单页面应用程序将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript 和 CSS。一旦页面加载完成了,SPA不会因为用户的操作而进行页面的重新加载或跳转。取而代之的是利用 JavaScript 动态的变换HTML的内容,从而实现UI与用户的交互。由于避免了页面的重新加载,SPA 可以提供较为流畅的用户体验。

可以很方便的在一个页面生命周期内控制子页面之间的数据传输。

例如向我们写的列表页,如果你只点击分页,页面中只会是表格中的内容改变,不会去重新加载整个页面

优点:

1.良好的交互体验
  单页应用的内容的改变不需要重新加载整个页面,获取数据也是通过Ajax异步获取,没有页面之间的切换,就不会出现“白屏现象”,也不会出现假死并有“闪烁”现象,页面显示流畅,web应用更具响应性和更令人着迷。

2.良好的前后端工作分离模式
  后端不再负责模板渲染、输出页面工作,后端API通用化,即同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端。

3.减轻服务器压力
  单页应用相对服务器压力小,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍。

缺点:

二、缺点
1.首屏加载慢
如果不对路由进行处理,在加载首页的时候,就会将所有组件全部加载,并向服务器请求数据,这必将拖慢加载速度;
通过查看Network,发现整个网站加载试讲长达10几秒,加载时间最长的就是js、css文件和媒体文件及图片
  解决方案:

Vue-router懒加载
    Vue-router懒加载就是按需加载组件,只有当路由被访问时才会加载对应的组件,而不是在加载首页的时候就加载,项目越大,对首屏加载的速度提升得越明显。

使用CDN加速
    在做项目时,我们会用到很多库,采用cdn加载可以加快加载速度。

2.不利于SEO
  seo 本质是一个服务器向另一个服务器发起请求,解析请求内容。但一般来说搜索引擎是不会去执行请求到的js的。也就是说,搜索引擎的基础爬虫的原理就是抓取url,然后获取html源代码并解析。 如果一个单页应用,html在服务器端还没有渲染部分数据,在浏览器才渲染出数据,即搜索引擎请求到的html是模型页面而不是最终数据的渲染页面。 这样就很不利于内容被搜索引擎搜索到。

  解决方案:

服务端渲染
    服务器合成完整的 html 文件再输出到浏览器

页面预渲染
路由采用h5 history模式
3.不适合开发大型项目
  大型项目中可能会涉及大量的DOM操作、复杂的动画效果,也就不适合使用Vue、react框架进行开发。

非单页:子页面之间的交互,在兼容性面前,更多会考虑URL的传输。而这种方式面对某个需要其他子页面数据来填充自身表单的子页面来说,就不是一个好办法,因为数据量很可能很大,让URL很长。

综合对比,选择单页面应用。

单页面应用程序的优缺点 - 浩荡九天 - 博客园

React如何优雅地写单页面应用? - 知乎

用React实现移动端单页应用 - 一扬 - 博客园

简单单页面的实现

https://blog.csdn.net/u013558749/article/details/68068519?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control

59.什么是高阶组件
高阶组件是参数为组件,返回值为新组件的函数

高阶组件用法及作用

60.如何创建refs?

import React from 'react'
class test extends React.Component{
state = {
myTest: 'jjj'
}
testRef = React.createRef() // 创建的是一个对象
render(){

    return(
        <div>
            <input ref={this.testRef}/>
            <button onClick={() =>{
            console.log("获取输入框中的值",this.testRefs.current.value)
            console.log(this.testRefs.current, '是一个对象,可以获取到DOM')
            }}>点我</button>
        </div>
        )
}

}
export default test

61.React-router单页面应用--路由管理;路由和组件;重定向;路由生命周期;懒加载

62什么时候使用状态管理器?

不同身份的用户有不同的使用方式(比如普通用户和管理员)
某个组件的状态需要共享
某个状态需要在任何地方都可以拿到
63.render函数中return如果没有使用()会有什么问题?

64.componentWillUpdate可以直接修改state的值吗

不可以,这样会导致无限循环报错
在react中直接修改state,render函数不会重新执行渲染,应使用setState方法进行修改
65.什么是渲染劫持

从字面意思理解呢

渲染指的是组件中的render函数return的JSX语法部分。那么劫持呢,是在渲染之前进行数据等操作的处理,修改了原来组件的渲染

控制组件从另一个组件输出的能力

在高阶组件中,组合渲染和条件渲染都是渲染劫持的一种,通过反向继承,不仅可以实现以上两点,还可以增强由原组件render函数产生的React元素。

实际的操作中 通过 操作 state、props 都可以实现渲染劫持

React的事件和普通的HTML事件有什么不同?

区别:

对于事件名称命名方式,原生事件为全小写,react 事件采用小驼峰
对于事件函数处理语法,原生事件为字符串,react 事件为函数
react 事件不能采用 return false 的方式来阻止浏览器的默认行为,而必须要地明确地调用preventDefault()来阻止默认行为
合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象,其优点如下:

兼容所有浏览器,更好的跨平台
将事件统一存放在一个数组,避免频繁的新增与删除(垃圾回收)
方便 react 统一管理和事务机制
事件的执行顺序为原生事件先执行,合成事件后执行,合成事件会冒泡绑定到 document 上,所以尽量避免原生事件与合成事件混用,如果原生事件阻止冒泡,可能会导致合成事件不执行,因为需要冒泡到document 上合成事件才会执行

React 组件中怎么做事件代理?它的原理是什么?

React基于Virtual DOM实现了一个SyntheticEvent层(合成事件层),定义的事件处理器会接收到一个合成事件对象的实例,它符合W3C标准,且与原生的浏览器事件拥有同样的接口,支持冒泡机制,所有的事件都自动绑定在最外层上。

在React底层,主要对合成事件做了:事件委派和自动绑定。

事件委派: React会把所有的事件绑定到结构的最外层,使用统一的事件监听器,这个事件监听器上维持了一个映射来保存所有组件内部事件监听和处理函数。
自动绑定: React组件中,每个方法的上下文都会指向该组件的实例,即自动绑定this为当前组件。
条件渲染

场景:返回按钮是否显示

import React,{component} from 'react'
export default class App extends Component{
state = {
list:[
{
id: 1,
isShow: false
},
{
id: 2,
isShow: true
}
]
}
render(){
return(



    {this.state.list.map(item =>{

  • {item.isShow}
    {item.isShow && }

  • })}


)
}
}

import React,{Component} from 'react'
class User extends Component{
render(){
return(

Weclome back!
)
}
}

class Guest extends Component{
render(){
return(

Weclome back!
)
}
}
export default class App extends Component{
state = {
isLogin: false
}
render(){
const isLogin = this.state
let button
if(isLogin){
button =
}else{
button =
}
return(

{button}
)
}
}

模仿vue中v-model指令,react实现类似双向绑定
通过onChange事件监听input的value值,在通过this.setState改变显示出来

react无状态组件和class类组件的区别

直观区别,函数组件代码量较少,相比类组件更加简洁
函数组件看似只是一个返回react元素的函数,其实体现的是无状态组件的思想,函数组件中没有this,没有state,也没有生命周期,这就决定了函数组件都是展示性组件,接收props,渲染dom,而不关注其他逻辑
因为函数组件不需要考虑组件状态和组件生命周期方法中的各种比较校验,所以有很大的性能提升空间
React中什么是纯函数

一个函数的返回结果只依赖其参数,并且执行过程中没有副作用

shouldComponentUpdate默认会有的吗

是的,每个组件都会有

React有哪几种方式改变state

this.forceUpdate this.setState :key值传递不同也可以 replaceState也可以改变

React组件传值有哪些方式

父传子:props 子传父:通过在父组件引入的子组件中传递一个函数并传参数,子组件去触发这个函数更改参数完成数据更新

跨多层组件传值:通过context api完成

React中要实现一键换ui样式有哪些方案

准备不同主题色的样式文件
将用户的选择记录在本地缓存中
每次进入应用时,读取缓存,根据缓存的信息判断要加载哪个样式文件即可
React声明周期及自己的理解

react的生命周期函数有:挂载,渲染/更新,卸载

如何配置React-Router

路由的动态加载模块

为什么要动态加载模块?

webpack在打包react应用时会将整个应用打包成一个js文件,当用户首次访问时,会加载整个js文件,当应用规模越来越大时,这个js文件所包含的数据量也越来越大,网站首屏渲染的速度也就会变慢

优化方法

1.多入口:利用webpack的entry配置多入口,将应用打包分割成多个js文件。适用于多页面应用。

2.去重:利用splitChunks去重,将公用的部分分离出来。

3.路由动态加载:利用import()方法细颗粒度的分割代码,将每一个路由到的组件从主bundle.js文件分离出来。

介绍路由的history

我们在用vue和react等前端渲染时,通常会有hash路由和history路由两种路由方式

hash 路由:监听 url 中 hash 的变化,然后渲染不同的内容,这种路由不向服务器发送请求,不需要服务端的支持;
history 路由:监听 url 中的路径变化,需要客户端和服务端共同的支持;
我们一步步实现这两种路由,来深入理解下底层的实现原理。我们主要实现以下几个简单的功能:

监听路由的变化,当路由发生变化时,可以作出动作;
可以前进或者后退;
可以配置路由;
深入理解前端中的 hash 和 history 路由 - 知乎

介绍Redux数据流的流程

Redux原理及工作流程_QcoY_的博客-CSDN博客_redux工作流程

Redux如何实现多个组件之间的通信,多个组件使用相同状态如何进行管理

使用过的Redux中间件

介绍redux,主要解决什么问题

redux请求中间件如何处理并发

React组件中怎么做事件代理

React组件事件代理的原理

深入理解React:事件机制原理 - OneForCheng - 博客园

React怎么做数据的检查和变化

props组件属性,专门用来连接父子组件间通信,父组件传输父类成员,子组件可以利用但不能编辑父类成员
state:专门负责保存和改变组价内部的状态
数据传递:在React中,父组件给子组件传递数据时,通过子组价设置props的方式,子组件取得props中的值,即可完成数据传递,被传递数据的格式可以是任何js可识别的数据结构props一般只作为父组件给子组件传递数据用,不要试图去修改自己的props

数据改变:props不能被自身修改,如果组件内部的属性发生变化使用state

this.setState({})

React会实时监听每个组件的props和state的值,一旦有变化,会立刻更新组件,将结果重新渲染到页面上,state,props

react-router怎么实现路由切换

react-router里的标签和标签有什么区别

Link组件最终会渲染为HTML标签,它的to,query,hash属性会被组合在一起并渲染为href属性。虽然Link被渲染为超链接,但在内部实现上使用脚本拦截了浏览器的默认行为,然后调用了history.pushState方法

Link 只负责触发 url 变更,Route 只负责根据 url 渲染组件

相比于 标签, 避免了不必要的渲染

React层面的性能优化

对于类士组件和函数式组件来看,都可以从以下几个方面去思考能够进行性能优化

减少重新render的次数
减少渲染的节点
降低渲染计算量
合理设计组件
减少重新render的次数

在react里时间耗时最多的一个地方是reconciliation,如果不执行render,也就不需要 reconciliation,所以可以看出减少render在性能优化过程中的重要程度了

使用import时,webpack对node_modules里的依赖会做什么

React中Dom结构发生变化后内部经历了哪些变化

React挂载的时候有3个组件,textComponent、composeComponent、domComponent,区别和关系,Dom结构发生变化时怎么区分data的变化,怎么更新,更新怎么调度,如果更新的时候还有其他任务存在怎么处理

Redux中异步的请求怎么处理

redux的设计思想

接入redux的过程

绑定connect的过程

Redux在状态管理方面解决了React本身不能解决的问题

遇到性能问题一般在哪个生命周期里解决

写react有哪些细节可以优化

React的事件机制(绑定一个事件到一个组件上)

React子父组件之间如何传值

介绍下React高阶组件,和普通组件有什么区别

页面上有1万个button如何绑定事件

循环绑定时的index是多少,为什么,怎么解决

页面上有一个input,还有一个p标签,改变input后p标签就跟着变化,如何处理

监听input的哪个事件,在什么时候触发

Redux怎么实现属性传递,介绍下原理

React-Router版本号

Redux状态管理器和变量挂载到window中有什么区别

React中setState后发生了什么

seetState()将总会触发一次重绘,除非在shouldComponentUpdate()中实现了条件渲染逻辑。如果可变对象被使用了,但又不能在shouldComponentUpdate() 中实现这种逻辑,仅在新state和之前的state存在差异的时候调用setState()可以避免不必要的重新渲染。通常state中只来管理和渲染有关的状态,从而保证setState改变状态和渲染有关的状态。这样子就可以避免不必要的重复渲染。其他和渲染无关的状态,可以直接以属性的形式保存在组件中,在需要的时候调用和改变,不会造成渲染。同时需要避免不必要的修改,当 state 的值没有发生改变的时候,尽量不要使用 setState 。虽然 shouldComponentUpdate 和PureComponent 可以避免不必要的重复渲染,但是还是增加了一层 shallowEqual 的调用,造成多余的浪费。

setState为什么默认是异步;setState什么时候是同步的

react设计思路

react常见的通信方式

父子组件通信
跨级组件通信
非嵌套组件通信
父子通信

父传子 --> props
子传父--->props+回调函数
跨级组件通信

props逐层传递(不考虑)
context传递
非嵌套组件通信(如兄弟组件等)

使用机制:消息订阅与发布

react组件通信的几种方式_卡布达。的博客-CSDN博客_react组件通信

React中组件通信的几种方式 - 简书

redux整体的工作流程

React数据流

哪些方法会触发React重新渲染?

setState()方法被调用

父组件重新渲染

重新渲染render会做些什么?

会对新旧VNode进行对比,也就是我们所说的Diff算法

对新旧两棵树进行一个深度优先遍历,这样每一个节点都会一个标记,在到深度遍历的时候,没遍历到一个节点,就把该节点和新的节点树进行对比,如果有差异就到放到一个对象里面

说说React有什么坑点

JSX做表达式判断的时候需要转为boolean类型

如果不使用!!b进行强转数据类型会在页面里面输出0

render() {
const b = 0;
return


{
!!b &&
这是一段文本

}

} react的理念是什么(拿函数式编程来做页面渲染)

为什么使用Hooks?

使用hooks理由

高阶组件为了复用,导致代码层级复杂
生命周期复杂
写成functional组件,无状态组件,因为需要状态,又改成了class,成本高
useState(保存组件状态)

const [state,setState] = useState(initialState)
hook原理

如何在React中使用innerHTML

增加dangerouslySetInnerHTML属性,并且传入对象的属性名叫_html

function Component(props){
return <div dnagerouslySetInnerHTML={{_html:'你好'}}>


}
66.说说你对react的渲染原理的理解

【第1386期】React从渲染原理到性能优化(一)

67.说说Context有哪些属性

68.怎么使用Context开发组件

69.React中在哪捕获错误?

百度安全验证

[react] React中在哪捕获错误?_「违规用户」的博客-CSDN博客_react 捕获错误

错误边界 – React

70.react组件的构造函数有什么用

提供了一个无需为每层组件手动添加props,就能在组件树间进行数据传递的方法

React 高阶组件、Render props、hooks 有什么区别,为什么要不断迭代

高频react面试题20道(附详解)_程序员成长指北-CSDN博客

虚拟DOM原理剖析

react动画特效

react组件化思想

这么高质量React面试题(含答案),看到就是赚到了! - 知乎

https://www.aliyue.net/11776.html

posted @ 2022-08-08 21:27  是豆腐啊  阅读(275)  评论(0编辑  收藏  举报