说说React相关面试题

             ****

Vue组件通信?

除了使用vuex外还有下面6种组件间的通信方式:

1、 props / $emit

父组件通过 props 向子组件传递数据,子组件通过 $emit 和父组件通信

(1)父组件向子组件传值(props的用法)
props的特点:

props只能是父组件向子组件进行传值,props使得父子组件之间形成一个单向的下行绑定。子组件的数据会随着父组件的更新而响应式更新。
props可以显示定义一个或一个以上的数据,对于接收的数据,可以是各种数据类型,同样也可以是传递一个函数。
props属性名规则:若在props中使用驼峰形式,模板中标签需要使用短横线的形式来书写。
(2)子组件向父组件传递数据($emit的用法)
$emit的特点:

$emit 绑定一个自定义事件,当这个事件被执行的时候就会将参数传递给父组件,而父组件通过v-on监听并接收参数

2、ref / $refs

这种方式也是实现父子组件之间的通信

ref:这个属性用在子组件上,它的用用就指向了子组件的实例,可以通过实例来访问组件的数据和方法

3、eventBus事件总线($emit / $on)

eventBus事件总线适用于父子组件、非父子组件等之间的通信,使用步骤如下:

(1)创建事件中心管理组件之间的通信
(2)发送事件 假设有两个兄弟组件firstCom和secondCom

4、依赖注入(provide / inject)

这种方式就是vue中依赖注入,该方法用于 父子组件之间 的通信。当然这里所说的父子不一定是真正的父子,也可以是祖孙组件,在层数很深的情况下,可以使用这种方式来进行传值。就不用一层一层的传递数据了。

provide和inject是vue提供的两个钩子,和data、methods是同级的。并且provide的书写形式和data一样。

provide 钩子用来发送数据或方法。
inject钩子用来接收数据或方法

5、$parent / $children

使用$parent可以让组件访问父组件的实例(访问的是上一级父组件的属性和方法)。
使用 $children 可以让组件访问子组件的实例,但是, $children 并不能保证顺序,并且访问的数据也不是响应式的。
注意:

通过 $parent 访问到的是上一级父组件的实例,可以使用 r o o t 来 访 问 根 组 件 的 实 例 在 组 件 中 使 用 root 来访问根组件的实例 在组件中使用 root访使children拿到的是所有的子组件的实例,它是一个数组,并且是无序的
在根组件 #app 上拿 $parent 得到的是 new Vue()的实例,在这实例上再拿 $parent 得到的是undefined,而在最底层的子组件拿 $children 是个空数组
$children 的值是数组,而 $parent是个对象

6、$attrs / $listeners

考虑一种场景,如果A是B组件的父组件,B是C组件的父组件。如果想要组件A给C组件传递数据,这种隔代传数据的情况该使用哪种方式呢?

如果是用props/ $emit 来一级一级的传递,确实可以完成,但是比较复杂;如果使用事件总线,在多人开发或者项目较大的时候,维护起来很麻烦;如果使用vuex,如果仅仅是传递数据,那可能有点浪费了。

针对上述情况,vue引入了 $attrs / $listeners,实组件之间的跨代通信。

$attrs:继承所有的父组件属性(除了props传递的属性、class 和 style),一般用在子组件的子元素上
$listeners:该属性是一个对象,里面包含了作用在这个组件上的所有监听器,可以配合 v-on=" $listeners " 将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件)
再说一下 inheritAttrs

默认值为true,继承所有的父组件属性除props之外的所有属性。
只继承class属性。
总结
根据以上对这6种组件间的通信方法,可以将不同组件间的通信分为4种类型:父子组件间通信、跨代组件间通信、兄弟组件间通信、任意组件间通信

1、父子组件间通信
子组件通过 props 属性来接受父组件的数据,然后父组件在子组件上注册监听事件,子组件通过 emit 触发事件来向父组件发送数据。
通过 ref 属性给子组件设置一个名字。父组件通过 $refs 组件名来获得子组件,子组件通过 p a r e n t 获 得 父 组 件 , 这 样 也 可 以 实 现 通 信 。 使 用 p r o v i d e / i n j e c t , 在 父 组 件 中 通 过 p r o v i d e 提 供 变 量 , 在 子 组 件 中 通 过 i n j e c t 来 将 变 量 注 入 到 组 件 中 。 不 论 子 组 件 有 多 深 , 只 要 调 用 了 i n j e c t 那 么 就 可 以 注 入 p r o v i d e 中 的 数 据 。 2 、 跨 代 组 件 间 通 信 跨 代 组 件 间 通 信 其 实 就 是 多 层 的 父 子 组 件 通 信 , 同 样 可 以 使 用 上 述 父 子 组 件 间 通 信 的 方 法 , 只 不 过 需 要 多 层 通 信 会 比 较 麻 烦 。 使 用 上 述 的 6 种 方 法 的 parent 获得父组件,这样也可以实现通信。 使用 provide/inject,在父组件中通过 provide提供变量,在子组件中通过 inject 来将变量注入到组件中。不论子组件有多深,只要调用了 inject 那么就可以注入 provide中的数据。 2、跨代组件间通信 跨代组件间通信其实就是多层的父子组件通信,同样可以使用上述父子组件间通信的方法,只不过需要多层通信会比较麻烦。 使用上述的6种方法的 parent使provide/injectprovideinjectinjectprovide2使使6attrs / $listeners方法。
3、兄弟组件间通信
通过 $parent + $refs 以父组件为中间人来获取到兄弟组件,也可以进行通信。
4、任意组件间通信
使用 eventBus ,其实就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。它的本质是通过创建一个空的 Vue 实例来作为消息传递的对象,通信的组件引入这个实例,通信的组件通过在这个实例上监听和触发事件,来实现消息的传递。
如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候采用上面这一些方法可能不利于项目的维护。这个时候可以使用 vuex ,vuex 的思想就是将这一些公共的数据抽离出来,将它作为一个全局的变量来管理,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。

说说你对vuex的理解?写出其原理的核心代码?

(1)vuex是多个组件,共享同一个数据的状态管理工具。只是父子之间的数据传递没必要使用vuex,小型项目官方都不推荐使用vuex,只会增加项目的负担,大型的项目并且是多个组件共享的用vuex更好
(2)vuex和localstorage两者应用场景不同。vuex是当前vue项目的全局状态对象,存放在内存中,一旦当前vue项目刷新,vuex的数据也将恢复默认值;而localstorage是存放在浏览器中的对象,即使刷新数据也仍然存在。
(3)对于这个问题,在创建 store 的时候传入 strict: true, 开启严格模式,那么任何修改state的操作,只要不经过mutation的函数,vue就会 throw error

const store = new Vuex.Store({
state,
strict:true
//开启严格模式后,只能通过mutation来改变状态(不支持异步)否则会报错
})
//下面的开启严格模式就会报错,不开启是可行的
console.log(store.state.count) //0
store.state.count = 3;
console.log(store.state.count) //3
注意:发布环境下不要开启严格模式,严格模式会深度监测状态树来检测不合规的状态变化,造成不必要的性能损失
但是真正原因是:
Vuex的state是响应式的,响应式就是状态改变页面组件也实时更新。但是要实现响应式必须通过提交mutation去改变state,并且还需要遵守一定的规则
image.png
下面从是什么,为什么,怎么用的角度来谈对vuex的理解
【1】vuex是什么
多个组件,共享,同一个数据的状态管理工具
vuex适用于大型单页应用,简单的应用使用 Vuex 可能是繁琐冗余的

【2】为什么
当在开发大型单页应用时,会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。如登录状态、加入购物车、音乐播放等。
或许你认为可以用传参的方法解决组件之间互相传值的问题。但是传参的方法对于多层嵌套的组件将会变得很繁琐,并且对于兄弟组件间的传递无能为力。所以vuex出现了,相当于一个“前端的数据库”。
Vuex主要用于解决组件之间同一状态的共享问题,它能把组件的共享状态抽取出来,当做一个全局单例模式进行管理。 这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。即Vuex采用集中式存储管理应用的所有组件的状态 这里的关键在于集中式存储管理。 这意味着本来需要共享状态的更新是需要组件之间的通讯,而现在有了Vuex,组件就都和store通讯了

【3】怎么用
安装使用步骤
1.安装
sudo cnpm install vuex -S
2.引入状态管理工具vuex
import vuex from ‘vuex’
import store from ‘./vuex/store’
3.main.js里面实例化
new Vue({
el: ‘#app’,
router, :style=“{ ‘left’: leftnum + ‘px’ }”
store,
components: { App },
template: ‘’
})
4.在src里面和views同级创建vuex文件里面store.js
import Vue from ‘vue’
import Vuex from ‘vuex’
Vue.use(Vuex)
const store = new Vuex.Store({
// 定义状态
state: {
//动态路由的数组
keepAlive:[],
//全局域名
domainName:“”,
}
})
export default store

5.使用:this.$store.state.名字

使用方法核心内容
(1)state 存放状态
(2)mutations 美[mjuːˈtion] 同步的,唯一更改state的方法是提交 mutation。
(3)getters 加工state成员给外界类似于计算属性
(4)actions 异步的,然后提交mutation去操作state
(5)modules 模块化状态管理

说说React生命周期中有哪些坑?如何避免?

在讨论React 的生命周期的时候,一定是在讨论类组件,因为函数组件并没有生命周期的概念,它本身就是一个函数,只会从头执行到尾巴

其实生命周期只是一个抽象的概念,大部分人看到生命周期想到的往往都componentDidMount,componentWilMount等等函数,然而这些其实并不是它的生命周期,只是在生命周期中按顺序执行的函数而已,挂载 --> 更新 --> 卸载 这一React的完整流程才叫生命周期

挂载阶段 – 指的是组件从初始化到完成加载的过程

constructor

constructor 是类通用的构造函数,常用于初始化,所以在过去,constructor 常用于初始化state和绑定函数
社区去除 constructor 的原因很明确:

constructor 中并不推荐去处理初始化以外的逻辑
constructor 本身并不是属于React的生命周期,它只是Class的一个初始化函数
通过移除constructor, 代码会变的更加的简洁
getDerivedStateFromProps

这个函数的作用是当 props 发生变化时来更新state,那么它的触发时机是什么时候呢?

当 props 被传入的时候
当 state 发生变化时
当 forceUpdate 被调用时
最常见的一个错误就是误认为只有当props发生变化时,getDerivedStateFromProps 才会被调用,而实际上只要父组件重新渲染时,getDerivedStateFromProps 就会被调用,所以是外部参数,

也就是 props 传入时就会发生变化。
依据官方的说法,它的使用场景是很有限的。

两种反模式的使用方式:

直接复制到 props 到 state
在 props 变化后修改 state
这两种写法除了增加代码的维护成本外,没有带来任何的好处。

UNSAFE_componentWillMount

也就是componentWillMount,在组件即将被挂载之前执行某些操作,目前已被弃用,因为在React的新的异步渲染机制下,该方法可能会被多次调用。

写过服务端渲染的同学应该会遇到过, componentWillMount 跟服务器端同构渲染的时候,如果在该函数中发起网络请求话,会发现请求在服务器和客户端各执行了一次,所以React 更推荐在componentDidMount 中去做网络请求等操作

render

render 函数返回的是 JSX 的数据结构,用于描述具体的渲染内容,但是 render函数并不会去真正的渲染组件,真正的渲染是依靠 React 操作 JSX 描述结构来完成,而且 render 函数应该是一个纯函数,不应该在里面产生副作用,比如调用 setState 函数(render 函数在每次渲染的时候都会被调用,而 setState 又会触发渲染,所以就会造成死循环)

componentDidMount

componentDidMount 用于在组件挂载完成时去做某些操作,比如发起网络请求等,componentDidMount 是在render之后被调用

至此 挂载阶段 基本算是完成

更新阶段

更新阶段是指:当外部 props 被传入,又或者当 state 发生改变时的阶段。

UNSAFE_componentWillReceiveProps

该函数已标记弃用,因为其功能可被 getDerviedStateFromProps 所替代

另外,当 getDerviedStateFromProps 存在时 UNSAFE_componentWillReceiveProps 不会被调用

getDerviedStateFromProps

同挂载阶段的表现一致。

shouldComponentUpdate

该方法通过返回true或者fasle来确定是否重新触发新的渲染,这也是性能优化的必争之地,通过添加判断条件来控制组件是否需要重新渲染

当前 React 的官方也给出了一个通用的优化方案,那就是PureComponent,PureComponent 的核心原理就是默认实现了一个 shouldComponentUpdate 函数,在这个函数中对 props 和 state 进行浅比较,用来判断是否重新触发更新。
render

同挂载阶段的表现一致

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate 方法是配合 React 新的异步渲染的机制,在DOM更新发生前被调用,其返回值将作为 componentDidUpate 的第三个参数

说说你对React中虚拟dom的理解?

当我们在实现页面性能优化的时候,我们一般在对浏览器做一些性能优化,重绘和重排一般会导致页面的重复刷新,造成性能低下。所以我们一般使用虚拟dom代替真实dom的方法来进行优化,真实dom的消耗是真实dom完全增删改+重绘和重排。虚拟dom的消耗是虚拟dom增删改+真实dom增删改+重绘和重排。真实dom的优点是简单易操作,缺点就是频繁的重排和重绘造成页面的性能低下。虚拟dom的优点是不易造成性能的浪费,也可以一端代码多端使用,形成一个多平台使用的效果,缺点是比真实dom多了一层真实dom的增删改,所以在首次渲染页面的时候速度比较慢。

调和阶段setState干了什么?

代码中调用setState之后,react会将传入的参数对象,与组件当前的状态合并,然后触发,然后react会重新渲染整个UI界面,在react得到元素树之后,react会自动计算出新树和老树的差异,然后根据差异对界面进行最小化的渲染,在差异计算法中,react能相对精准的知道哪些位置发生了改变,以及应该如何改变。这就保证了按需更新,而不是全部重新渲染。

React组件之间如何通信?

父组件向子组件传递:子组件通过props属性能接收父组件传递过来的参数
子组件向父组件传递:父组件向子组件传一个函数,通过这个函数的回调,拿到组件传递的值
兄弟组件之间的通信:通过使用父组件传递

说说redux的实现原理是什么,写出其原理的核心代码?

1.将应用的状态统一放到state中,由store来管理state。
2.reducer的作用是返回一个新的state。
3.UI层每一次状态的改变都应通过action去触发,actions传入对应的reducer中,reducer的作用是返回一个新的state。UI层每一次状态的改变都应通过action去触发,action传入相应的state。UI层每一次状态的改变都应通过action去触发,action传入相应的reducer中,reducer返回一个新的state跟新store中存放的state。
4.可以添加中间件对提交的dispatch进行重写。
核心:createStore创建仓库,接受reducer作为参数
BindActioncreateor绑定dispatch和action的关系
combineReducers合并多个reducers
Dispatch触发
Compose整合多个中间件

说说Connect组件的原理是什么?

react-redux用于连接react组件及redux,使用redux管理状态。其中connect方法是关键,connect([mapStateToProps], [mapDispatchToProps])(component)
看connect使用方法就知道是高阶组件,接收参数为mapStateToProps和mapDispatchToProps俩个方法,返回的函数接收参数是组件,从而返回一个新的组件

说说react 中jsx语法糖的本质?

JSX是语法糖,通过babel转成React.createElement函数,JavaScript中参数在函数内部是以一个数组表示的,函数接收的始终是一个数组,当传入多个参数时,通过获取第三个以及以后参数

说说你对redux中间件的理解?常用的中间件有哪些?实现原理?

答:Redux是一个实现集中管理的容器,遵循三大基本原则:单一数据源,state是只读的,使用纯函数来执行修改
常用中间件:redux-thunk
实现原理:数据都放到store,一个组件改变了store里的数据内容,其他组件就能感知到store的变化,再来取数据,从而间接的实现了这些数据传递的功能

props和state相同点和不同点?render方法在哪些情况下会执行?

相同点:props和state都会触发渲染更新
props和state都是js对象
可以从父组件得到初始值props和state的初始值
不同点:props是指组件间传递的一种方式,props自然也可以传递state。由于	React	的数据流是自上而下的,所以是从父组件向子组件进行传递;另外组件	内部的	this.props属性是只读的不可修改!
state是组件内部的状态(数据),不能够直接修改,必须要通过setState来	改变值的状态,从而达到更新组件内部数据的作用。
render会在类组件调用 setState 修改状态:函数组件通过useState hook修改	状态时候触发

react新出来两个钩子函数是什么?和删掉的will系列有什么区别?

用 getDerivedStateFromProps替换了 compoentWillMount和compontWillReceiveProps生命周期函数,解决还未渲染完成Dom导致绑定的方法存在内存中,造成内存泄露
用getSnapshotBeforeUpdate函数替换componetWillUpdate方法,避免和CompoentDidUpdate函数中获取数据不一致的问题

CDN的特点及意义?

CDN是节点分发的意思,也就是说在一片区域内进行网络分发机制,在同一片区域内的用户在获取静态资源的时候可以通过去离自己近的节点去获取资源。这样提升了访问页面的速度,提高了用户体验。但是有一个缺点就是如果是第一个用户的话他的访问速度会很慢,但是他请求过后,在同一区域内的其他人进行资源请求的时候速度会很快。

什么是闭包,应用场景是什么?

闭包就是可以访问其他函数内部变量的函数,我们通常用它来定义私有化的变量和方法,创建一个闭包最简单的方法就是在一个函数内创建一个函数,它有三个特性是 函数内可以再嵌套函数,内部函数可以访问外部的方法和变量,方法和变量不会被垃圾回收机制回收
应用场景:
任何闭包的使用场景都离不开这两点:
创建私有变量
延长变量的生命周期

从浏览器地址栏输入url到显示页面的步骤?

1.输入url ( 协议、网络地址、资源路径 )
2.查看浏览器缓存,看是否有缓存,如果有缓存,继续查看缓存是否过期,如果没有过期,直接返回缓存页面,如果没有缓存或者缓存过期,发送一个请求。
3.浏览器解析url地址,获取协议、主机名、端口号和路径。
4.获取主机ip地址过程,包括浏览器缓存,主机缓存,路由器缓存
5.浏览器发起和服务器的TCP连接,执行三次握手
6.三次握手连接后,浏览器发送一个http请求
7.服务器收到请求,转到相关的服务程序,期间可能需要连接并操作数据库(主要分get和post请求)
8.服务器看是否需要缓存,服务器处理完请求,发出一个响应
9.服务器并根据请求头包含信息决定是否需要关闭TCP连接(如需关闭,则需要四次挥手过程)
10.浏览器对接收到的响应进行解码
11.浏览器解析收到的响应并根据响应的内容,启动渲染引擎,创建render 树

介绍一下你对浏览器内核的理解?

主要分为渲染引擎和JS引擎
渲染引擎:负责取得网页的内容,整理讯息,以及计算网页的显示方式,然后输出到显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不同。所有网页浏览器、电子邮件客户端以及它需要编辑、显示网络内容的应用程序都需要内核。
JS引擎:解析和执行JavaScript来实现网页的动态效果。

清除浮动的几种方式?各自的优缺点?

1.使用空标签清除浮动clear:both。
优点:通俗易懂,容易掌握
缺点:会添加很多无意义的空标签
2.父级div定义overflow:hidden
优点:简单,代码少,浏览器支持好
缺点:不能和position配合使用,因为超出的尺寸的会被隐藏

说说你对koa中洋葱模型的理解?

koa是一个精简的node框架,最大特点就是独特的中间件流程控制,核心工作包括两个方面,第一将node原生的req和res封装成一个context对象。第二基于async和await的中间键洋葱模型机制。洋葱模式是以next函数为分割点由外到内执行request的逻辑,然后在由内到外执行response的逻辑。洋葱模式的核心原理就是借助compose方法。

如果需要手动写动画,你认为最小时间间隔是多久,为什么?

答:多数显示器默认频率是60Hz,即1秒刷新60次,所以理论上最小间隔为1/60*1000ms = 16.7ms。

说说你对webSocket的理解?

WebSocket是一种基于TCP的全双工通信协议,在应用层。建立WebSocket连接之后,客户端与服务端交流更方便,客户端只需要向服务端发送一次请求,服务端主动向客户端发送消息,WebSocket应用场景一般有即时聊天室,常用事件有open,message,error,close,常用方法有send,close

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值