1.Vue组件通信?
- props 和 $emit (常用)
- ref / refs
- eventBus-中央事件总线(emit/emit / on)(非父子组件间通信)
- attrs和attrs 和 listeners
- parent和parent和 children
- provide和inject (依赖注入)
- vuex
vue组件之间的通信6种
父子通信:props/ $emit
兄弟通信:eventBus(emit/emit / on)
vue 的状态管理器,存储的数据是响应式:vuex
多级组件嵌套:attrs/attrs / listeners / inheritAttrs
注入依赖:provide/inject
组件访问:parent/parent / children与 ref
props和 $emit
父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过$emit触发事件来做到的。
ref / refs
为子组件绑定 ref,父组件通过调用refs调用子组件的方法或属性
eventBus-中央事件总线(emit/emit / on)
eventBus事件总线适用于父子组件、非父子组件等之间的通信
新建一个Vue 事件bus对象,然后通过bus.emit触发事件,bus.emit触发事件,bus.on监听触发的事件。
attrs/attrs/ listeners 针对跨级通信
对于多层嵌套比较方便,每层都去绑定事件和属性,
attrs和attrs和 listeners是两个对象,attrs里存放的是父组件中绑定的非props属性,attrs 里存放的是父组件中绑定的非 props 属性,listeners里存放的是父组件中绑定的非原生事件。inheritAttrs选项则为是否挂载到组件元素的attribute。
parent和parent 和 children
在组件内部可以直接通过子组件parent对父组件进行操作,父组件通过parent对父组件进行操作,父组件通过children对子组件进行操作
provide/inject
父组件通过provide提供值
子组件通过inject获取值
vuex处理组件之间的数据交互
如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。
父子通信:
父向子传递数据是通过 props,子向父是通过 events( $emit )
通过父链 / 子链也可以通信(parent/parent / children)
ref 也可以访问组件实例
provide / inject API
attrs/attrs/listeners
兄弟通信:
Bus
Vuex
跨级通信:
Bus
Vuex
provide / inject
attrs/attrs / listeners
2.说说你对vuex的理解?写出其原理的核心代码?
什么是vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。
vuex的五大核心属性:state,getter,mutation,action,module
state:用于存储维护组件的公共状态
state:存储数据,存储状态;在根实例中注册了store 后,用this.$store.state来访问;对应vue里面的data;存放数据方式为响应式,vue组件从store中读取数据,如数据发生变化,组件也会对应的更新。
getters:用于对state中的数据进行相关处理后并返回,类似于计算属性
getter:可以认为是 store 的计算属性,它的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
mutations:是修改state的唯一途径,进行的是同步操作
mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
actions:要执行的操作,可以是同步或异步事件
action:包含任意异步操作,通过提交 mutation 间接更变状态。
modules:内部可以存放多个仓库配置对象,用于对仓库进行模块划分
module:将 store 分割成模块,每个模块都具有state、mutation、action、getter、甚至是嵌套子模块。
vuex的工作流程
- 通过dispatch去提交一个actions
- 在actions接收到事件后,在actions中执行一些同步或异步操作
- 根据不同的情况分发给不同的mutations,actions通过commit触发mutations
- mustations在触发后就会去更新state
- 在state更新完毕后,就会通知vue进行渲染
3.说说React生命周期中有哪些坑?如何避免?
getDerivedStateFromProps 容易编写反模式代码,使受控组件和非受控组件区分模糊
componentWillMount 在 React 中已被标记弃用,不推荐使用,主要的原因是因为新的异步架构会导致它被多次调用,所以网络请求以及事件绑定应该放到 componentDidMount 中
componentWillReceiveProps 同样也被标记弃用,被 getDerivedStateFromProps 所取代,主要原因是性能问题。
shouldComponentUpdate 通过返回 true 或者 false 来确定是否需要触发新的渲染。主要用于性能优化。
componentWillUpdate 同样是由于新的异步渲染机制,而被标记废弃,不推荐使用,原先的逻辑可结合 getSnapshotBeforeUpdate 与 componentDidUpdate 改造使用。
如果在 componentWillUnmount 函数中忘记解除事件绑定,取消定时器等清理操作,容易引发 bug。
如果没有添加错误边界处理,当渲染发生异常时,用户将会看到一个无法操作的白屏,所以一定要添加。
4.说说你对React中虚拟dom的理解?
虚拟 DOM 不会进行排版与重绘操作,而真实 DOM 会频繁重排与重绘
使用虚拟 DOM 的优势如下:
简单方便: 如果使用手动操作真实 DOM 来完成页面,繁琐又容易出错,在大规模应用下维护起来也很困难
性能方面: 使用 Virtual DOM,能够有效避免真实 DOM 数频繁更新,减少多次引起重绘与回流,提高性能
跨平台:React 借助虚拟 DOM,带来了跨平台的能力,一套代码多端运行
缺点:
在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化
首次渲染大量 DOM 时,由于多了一层虚拟 DOM 的计算,速度比正常稍慢
5.调和阶段setState干了什么?
(1)代码中调用 setState 函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。
(2)经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面;
(3)在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染;
(4)在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。
6.React组件之间如何通信?
1.父组件向子组件通讯:
父组件可以向子组件传入props的方式,向子组件进行通讯。
2.子组件向父组件通讯:
props+回调的方式,父组件向子组件传递props进行通讯,此props为作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到⽗组件的作⽤域中。
3.兄弟组件通信:
兄弟组件之间的传递,则父组件作为中间层来实现数据的互通,通过使用父组件传递
例:组件A – 传值 --> 父组件 – 传值 --> 组件B
4.跨层级通讯:
Context 设计⽬的是为了共享那些对于⼀个
组件树⽽⾔是“全局”的数据,
使用context提供了组件之间通讯的一种方式,可以共享数据,其他数据都能读取对应的数据
例如当前认证的⽤户、主题或⾸选语⾔,对于跨越多层的全局数据通过 Context 通信再适合不过。
5.发布订阅者模式:
发布者发布事件,订阅者监听事件并做出反应,我们可以通过引⼊event模块进⾏通信。
6.全局状态管理工具:
借助Redux或者Mobx等全局状态管理⼯具进⾏通信,这种⼯具会维护⼀个全局状态中⼼Store,并根据不同的事件产⽣新的状态。
7.说说redux的实现原理是什么,写出其原理的核心代码?
原理
- 将应用的状态统一放到state中,由store来管理state。
- reducer的作用是 返回一个新的state去更新store中对用的state。
- 按redux的原则,UI层每一次状态的改变都应通过action去触发,action传入对应的reducer 中,reducer返回一个新的state更新store中存放的state,这样就完成了一次状态的更新
- subscribe是为store订阅监听函数,这些订阅后的监听函数是在每一次dipatch发起后依次执行
- 可以添加中间件对提交的dispatch进行重写
核心API
- createStore 创建仓库,接受reducer作为参数
- bindActionCreator 绑定store.dispatch和action 的关系
- combineReducers 合并多个reducers
- applyMiddleware 洋葱模型的中间件,介于dispatch和action之间,重写dispatch
- compose 整合多个中间件
8.说说Connect组件的原理是什么?
connect是一个高阶函数,它真正连接 Redux 和 React,包在我们的容器组件的外一层,接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。
原理:
首先传入mapStateToProps、mapDispatchToProps,然后返回一个生产Component的函数(wrapWithConnect),然后再将真正的Component作为参数传入wrapWithConnect,这样就生产出一个经过包裹的Connect组件,该组件具有:
(1)通过props.store获取祖先Component的store
(2)props包括stateProps、dispatchProps、parentProps,合并在一起得到nextState,作为props传给真正的Component
(3)componentDidMount时,添加事件this.store.subscribe(this.handleChange),实现页面交互
(4)shouldComponentUpdate时判断是否有避免进行渲染,提升页面性能,并得到nextState
(5)componentWillUnmount时移除注册的事件this.handleChange
9.说说react 中jsx语法糖的本质?
Jsx是语法糖,实质是js函数,需要babel来解析,核心函数是React.createElement(tag,{attrbuties},children),参数tag是标签名可以是html标签和组件名,attrbuties参数是标签的属性,children参数是tag的子元素。用来创建一个vnode,最后渲染到页面上。
10.说说你对redux中间件的理解?常用的中间件有哪些?实现原理?
理解:
中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的
Redux中,中间件就是放在就是在dispatch过程,在分发action进行拦截处理
本质上一个函数,对store.dispatch方法进行了改造,在发出 Action和执行 Reducer这两步之间,添加了其他功能
常用中间件:
redux-thunk:用于异步操作
redux-logger:用于日志记录
实现原理:
所有中间件被放进了一个数组chain,然后嵌套执行,最后执行store.dispatch。可以看到,中间件内部(middlewareAPI)可以拿到getState和dispatch这两个方法内部会将dispatch进行一个判断,然后执行对应操作
11.props和state相同点和不同点?render方法在哪些情况下会执行?
不同点:
- props 是外部传递给组件的,而 state 是在组件内被组件自己管理的,一般在 constructor 中初始化
- props 在组件内部是不可修改的,但 state 在组件内部可以进行修改
- state 是多变的、可以修改
相同点:
- 两者都是 JavaScript 对象
- 两者都是用于保存信息
- props 和 state 都能触发渲染更新
触发时机
render的执行时机主要分成了两部分:
- 类组件调用 setState 修改状态
- 函数组件通过useState hook修改状态
12.react新出来两个钩子函数是什么?和删掉的will系列有什么区别?
新增了下面两个生命周期方法:
getDerivedStateFromProps
getSnapshotBeforeUpdate
getDerivedStateFromProps 该方法类似于 componentWillReceiveProps,可以用来控制 props 更新 state 的过程。它返回一个对象表示新的 state。如果不需要更新组件,返回 null 即可。
用 getDerivedStateFromProps替换了 compoentWillMount和compontWillReceiveProps生命周期函数,解决还未渲染完成Dom导致绑定的方法存在内存中,造成内存泄露
getSnapshotBeforeUpdate 方法在 React 对视图做出实际改动(如 DOM 更新)发生前被调用,返回值将作为 componentDidUpdate 的第三个参数。
用getSnapshotBeforeUpdate函数替换componetWillUpdate方法,避免和CompoentDidUpdate函数中获取数据不一致的问题
13.CDN的特点及意义?
CDN 意为内容分发网络,是基于现有网络的智能虚拟网络,分布在世界各地的边缘服务器上。
基本思路:
避免互联网上可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输更快更稳定。
特点
本地缓存加速: 提高了企业网站(尤其是包含大量图片和静态页面的网站)的访问速度,大大提高了上述网站的稳定性。
镜像服务: 消除了不同运营商之间互联瓶颈带来的影响,实现了跨运营商的网络加速,保证了不同网络的用户都能获得良好的接入质量。
远程加速: 远程访问用户根据DNS负载均衡技术智能自动选择缓存服务器,选择最快的缓存服务器加速远程访问。
带宽优化: 自动生成服务器的远程镜像缓存服务器。远程用户访问时,可以从缓存服务器读取数据,减少远程访问的带宽,分担网络流量,减轻原WEB服务器的负载。
集群抗攻击: 广泛分布的CDN 节点加上节点间的智能冗余机制,可以有效防止黑客入侵,降低各种D.D.O.S攻击对网站的影响,同时保证更好的服务质量。
14.什么是闭包,应用场景是什么?
闭包(closure)指有权访问另一个函数作用域中变量的函数。
简单理解就是 ,一个作用域可以访问另外一个函数内部的局部变量。
闭包形成的条件
- 函数嵌套
- 将内部函数作为返回值返回
- 内部函数必须使用到外部的变量
闭包的使用场景
- setTimeout
- 回调
- 函数防抖
- 封装私有变量
15.从浏览器地址栏输入url到显示页面的步骤?
- 浏览器的地址栏输入URL并按下回车。
- 浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
- DNS解析URL对应的IP。
- 根据IP建立TCP连接(三次握手)。
- 发起HTTP请求。
- 服务器处理请求,浏览器接收HTTP响应。
- 渲染页面,构建DOM树。
- 关闭TCP连接(四次挥手)。
16.介绍一下你对浏览器内核的理解?
浏览器内核是浏览器的核心,也称“渲染引擎”,用来解释网页语法并渲染到网页上,浏览器内核决定了浏览器该如何显示网页内容以及页面的格式信息
浏览器内核主要分成两部分: 渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:
负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。
JS引擎:
解析和执行javascript来实现网页的动态效果。
17.清除浮动的几种方式?各自的优缺点?
方法一:额外标签法
给谁清除浮动,就在其后额外添加一个空白标签 ,给其设置clear:both。
优点: 通俗易懂,书写方便。
缺点: 添加许多无意义的标签,结构化比较差。
clear:both :本质就是闭合浮动, 就是让父盒子闭合出口和入口,不让子盒子出来 。
方法二:父元素添加overflow:hidden 通过触发BFC方式,实现清除浮动
优点: 代码简洁
缺点: 内容增多的时候容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素。
方法三:使用after伪元素清除浮动
优点: 符合闭合浮动思想,结构语义化正确。
缺点:ie6-7不支持伪元素:after,使用zoom:1触发
方法四:使用before和after双伪元素清除浮动
优点: 代码更简洁
缺点: 用zoom:1触发hasLayout.
方法五:为父元素设置高度
优点: 简单粗暴直接有效,清除了浮动带来的影响
缺点: 需要手动添加高度,如何后面的高度发生变化,还要再次修改高度,给后期的维护带来麻烦。
18.说说你对koa中洋葱模型的理解?
Koa
Koa是一个精简的node框架,被认为是第二代Node框架,其最大的特点就是独特的中间件流程控制,是一个典型的洋葱模型,它的核心工作包括下面两个方面:
将node原生的req和res封装成为一个context对象。
基于async/await的中间件洋葱模型机制。
洋葱模型
Koa的洋葱模型是以next()函数为分割点,先由外到内执行Request的逻辑,然后再由内到外执行Response的逻辑,这里的request的逻辑,我们可以理解为是next之前的内容,response的逻辑是next函数之后的内容,也可以说每一个中间件都有两次处理时机。洋葱模型的核心原理主要是借助compose方法
19.如果需要手动写动画,你认为最小时间间隔是多久,为什么?
大多数显示器的默认频率是60hz(即一秒刷新60次),每刷新一次时间需要1000ms/60=16.7ms,所以理论上最小时间间隔是16.7ms。
20.说说你对webSocket的理解?
理解
WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)
它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯的目的
Websocket是一个持久化的协议
原理
websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
在websocket出现之前,web交互一般是基于http协议的短连接或者长连接
websocket是一种全新的协议,不属于http无状态协议,协议名为"ws"