对react的理解,以及一些react特性
首先react是用于构建用户页面的js框架
理解
只提供了ui层面的解决方案。遵循组件设计模式,声明式编程范式和 函数式编程概念以使前端应用程序更高效。使用虚拟dom来有效地操作dom, 遵循从该届组件到底姐组件的单项数据流。帮助我们将界面成了各个独立的小 块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面。
react类组件使用一个名为render()的方法或者函数组件return,接收输 入的数据并返回需要展示的内容。
react特点:
jsx语法、单项数据绑定、虚拟dom、声明式编程、 component、
react存在的优势:
灵活高效、声明式的设计,简单使用、组件 式开发,提高代码复用率、单项响应的数据流会双向绑定的更安全,速度更快
Real diff算法是怎么运作的?
三大策略
Tree diff
Component diff
Element diff
Tree diff :
react通过updateDepth对Virtual Dom 树进行层级控制
对树的分层比较,两颗树只对同一层级节点进行比较,如果节 点不存在时,则该节点及其子节点会被完全删除,不会进一步的比较
只需遍历一次 就能完成整颗树的比较
如果出现节点的跨层级操作,diff只会简单的考虑同层级的节点 位置变换,如果是跨层级的话 只有创建节点和删除节点的操作
Component diff:
React对不同组件的比较 也有三种策略
1.同一类型的两个组件 按原策略(层级比较)继续比较 virtual Dom 树
2.同一类型的两个组件 组件A变化为组件B时,可能 Virtual DOM没有任何变化,如果知道这点(变化的过程中, Virtual DOM没有改变),可节省大量计算时间 可以通过 shuoldComponentUpdate()来判断是否需要判断计算
3.不同类型的组件 将一个要被改变的组件判断为脏组件 从而替换整个组件的节点
Element Diff:
当节点处于同一层级时,diff提供三种节点操作:删除、 插入、移动
Diff的不足和待优化的地方
尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大 或更新操作过于频繁的时候。会印象react的性能
React中虚拟dom的理解?
因为操作真实dom耗费性能代价太高,所以react内部使用js实现了一套dom结构,在每次操作在和真实dom响应前,使用实现好的diff算法,对虚拟dom比较。递归找出有变化的dom节点,然后对其进行更新操作。为了实现虚拟dom,我们需要把每一种 节点类型抽象成对象,每一种节点类型有自己的属性,也就是prop。每次进行diff时,react会先比较该节点类型,假如节点类型不一样。那么react会直接删除节点,然后创建新的节点插入到其中,加入节点类型一样,那么会比较prop是否有更新,假如有prop不一样,那么react会判定该节点有更新,那么重新渲染该节点,然后在对其子节点进行比较,一层一层往下,知道没有子节点
react hook的理解?
Hook 可以实现代码逻辑聚合,逻辑复用 Hoc嵌套地狱 代替class
好处:
跨组件复用:
hooks最为官方的底层api 最为轻量,而且改造成本小,不会影响原来的组件层次结构和传说中的嵌套地狱
类定义更为复杂:
不同生命周期会使逻辑变得分散且混乱,不易维护管理,, 时刻需要关注this的指向问题 代码的复用代价高,高阶组件的使用 经常会是整个组件树变得臃肿 时刻需要关注this的指向问题
状态与UI隔离:
正是由于 Hooks 的特性,状态逻辑会变成更小的粒度,并且极容易被抽象成一个自定义 Hooks,组件中的状态和 UI 变得更为清晰和隔离。
受控组件和非受控组件的理解?应用场景?
受控组件
由React控制的输入表单元素而改变其值的方式,称为受控组件。
非受控组件
非受控组件指的是,表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值。在非受控组件中,可以使用一个ref来从DOM获得表单值。
Connect组件的原理是什么?
首先connect之所以会成功,是因为Provider组件:
在原应用组件上包裹一层,使原来整个应用成为Provider的子组件 接收Redux的store作为props,通过context对象传递给子孙组件上的connect
connect做了些什么。它真正连接 Redux 和 React,它包在我们的容器组件的外一层,它接收上面 Provider 提供的 store 里面的state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件
connect是一个高阶函数,首先传入mapStateToProps、mapDispatchToProps,然后返回一个生产Component的函数(wrapWithConnect),然后再将真正的Component作为参数传入wrapWithConnect,这样就生产出一个经过包裹的Connect组件
说说AMD、CMD、commonJS模块化规范的区别?
首先,CommonJS规范的特点:
对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
当使用require命令加载某个模块时,就会运行整个模块的代码。
当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面 的操作。
AMD规范则是非同步加载模块,允许指定回调函数。
由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所 以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。
说说package.json中版本号的规则?
版本号的格式:X.Y.Z,分别代表主版本号、次版本号及补丁版本号;含义:
X:向下不兼容,大版本的升级
Y:新增功能,向下兼容
Z:bug的修复
^0.1.0:支持0.1.0 ~ 1.0.0之内的所有版本。
~0.1.0:支持0.1.0 ~ 0.2.0之内的所有版本。
0.1.0:锁定0.1.0版本。
>=0.1.0:支持大于等于0.1.0之后的所有版本。
*:任意版本。
由此可见:^表示大版本的升级,~表示小版本的升级。
React render方法的原理,在什么时候会触发?
在类组件和函数组件中,render函数的形式是不同的。
在类组件中render函数指的就是render方法;而在函数组件中,指的就是整个函数组件。
在render函数中的jsx语句会被编译成我们熟悉的js代码
在render过程中,React 将新调用的 render函数返回的树与旧版本的树进行比较,这一步是决定如何更新 DOM 的必要步骤,然后进行 diff 比较,更新 DOM树
触发时机:
类组件调用 setState 修改状态:
函数组件通过useState hook修改状态:
说说你对koa中洋葱模型的理解?
Koa是一个精简的node框架,被认为是第二代Node框架,其最大的特点就 是独特的中间件流程控制,是一个典型的洋葱模型,它的核心工作包括 下面两个方面:
将node原生的req和res封装成为一个context对象。
基于async/await的中间件洋葱模型机制。
Koa的洋葱模型是以next()函数为分割点,先由外到内执行Request的逻辑,然后再由内到外执行Response的逻辑,这里的request的逻辑,我们可以理解为是next之前的内容,response的逻辑是next函数之后的内容,也可以说每一个中间件都有两次处理时机。洋葱模型的核心原理主要是借助compose方法。
说说你对webSocket的理解?
WebSocket是一种基于TCP的全双工通信协议,在应用层。
1、传统上的HTTP协议它是无状态的,服务器不能够识别是哪个客户端发送的请求,不能够保存状态。
2、WebSocket弥补了这一问题,在客户端向服务端发送请求之后,服务器处理请求并返回到客户端,使用WebSocket可以使得服务器主动向浏览器推送消息