2021年高级前端进阶之路
Posted 四哥-云上
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021年高级前端进阶之路相关的知识,希望对你有一定的参考价值。
YYDS 2021年高级前端进阶之路
1.两边固定,中间自适应布局(1.用flex;2.用display:left;3.用相对定位和绝对定位结合)
2.js判断字符串中出现次数最多的字符(1.用for循环将字符串字符和出现次数push到一个新对象中;2.在这个新对象中用for in进行比较,分别找出次数最多的字符和出现次数。)
3.Vue.set的用法及场景(1.vue中检测不到对象属性的添加和删除;2.通过数组的下标去修改数组的值,数据已经被修改了,但是不触发updated函数,视图不更新。原理:vue.$set是能让vue知道你添加了属性, 它会给你做处理。)
4.Vue自定义指令的钩子函数及使用场景
4.1 钩子函数:bind,inserted,update,componentUpdated,unbind)
4.2 函数参数:el,binding,vnode,oldVnode
4.3 使用场景:按钮级别的权限控制
5.Vue页面渲染过程 (
5.1 加载文件执行顺序:1.打包配置位置;2.index.html;3.main.js;4.路由文件,将组件渲染到router-view;5.router-view中加载layout;6.Layout加载Navbar,Sidebar,AppMain
5.2 Vue内部页面执行顺序:1.把模板编译为render函数;2.实例进行挂载,根据根节点render函数的调用,递归生成虚拟DOM;3.对比虚拟DOM,渲染到真实DOM;4.组件内部发生变化,data作为props重新调用render函数,生成虚拟DOM,重复第3步.
6.React Hooks
6.1 为何用hooks(1.组件之间的逻辑状态难以复用;2.大型复杂组件难以拆分;3.Class语法的使用不友好)
6.2 hooks优点(1.没有破坏性改动,完全可选;2.更容易复用代码,复用状态;3.函数式编程风格,清爽优雅;4.代码量少;5.更容易拆分)
6.3 hooks缺点 (1.是React16.8版本的新增特性;2.因为闭包造成状态不同步;3.数组的push,pop,splice方法直接改变原数组,使用useState无法获取更新;4.useState初始化只初始化一次;5.useEffect内部不能修改state;6.useEffect依赖引用类型会出现死循环;7.不要在循环,嵌套,条件函数中调用hook,会产生顺序不一致问题)
6.4 解决闭包的坑 (闭包造成每次输出原来的state。可以通过useRef来保存state)
6.5 常用的Hooks有哪些 (1.useState()状态钩子;2.useContext()共享状态钩子;3.useReducer()状态钩子,很像redux;4.useEffect()副作用钩子,两个参数,一个是异步操作,一个是数组依赖项;5.useRef()获取组件实例,渲染周期之间共享数据的存储;6.useMemo缓存数据,useCallback缓存函数,常见的优化策略)
useCallback(fn,deps)相当于useMemo(()=>fn,deps),经常用在下面两种场景:
6.5.1 要保持引用相等;对于组件内部用到的 object、array、函数等
6.5.2 用在了其他 Hook 的依赖数组中,或者作为 props 传递给了下游组件,应该使用 useMemo/useCallback)
6.6 useEffect为什么有时候会出现无限重复请求的问题 (可能1.未设置依赖参数,每渲染一次就触发一次;可能2.所设置的依赖项总是会变。解决:useCallback包一层,或者useMemo)
6.7 使用hooks模拟生命周期 (可以封装一个模拟的js,然后各处都可以调用)
6.7.1 使用useState模拟constructor 代码:const [count, setCount] = useState(0)
6.7.2 使用useEffect模拟componentDidMount 代码:useEffect(() => { fn() }, [])
6.7.3 使用useMemo模拟shouldComponentUpdate 代码:React.useMemo((props) => {// your component})
6.7.4 使用useEffect+useState模拟componentDidUpdata 代码:useEffect(() => fn() ));
6.7.5 使用useEffect模拟componentUnMount 代码:useEffect(() => fn(), [])
6.8 模拟的生命周期和class中的生命周期有什么区别 (1.默认的useEffect(不带[])中return的清理函数,默认情况下在每次useEffect执行前都会执行,并不是只有组件卸载的时候执行; 2.useEffect在副作用结束之后,会延迟一段时间执行,并非同步,和compontDidMount有本质区别。遇到dom操作,最好使用useLayoutEffect。)
6.9 Hooks相比HOC和Render Prop有哪些优点?(1.hoc和render prop都是一种开发模式,将复用逻辑提升到父组件,容易嵌套过多,过度包装;2.hooks是react的api模式,将复用逻辑取到组件顶层,能够避免 HOC 和 Render Props 带来的「嵌套地狱」。)
6.10 Function Component与Class Component区别
6.10.1 对于class component来说:(1.首先state是不可变(Immutable),setState后生成一个全新的state引用;2.通过this.state方式读取state,所以每次代码执行都会拿到最新的state引用。)
6.10.2 对于function component来说:(1.useState 产生的数据也是不可变 Immutable 的,通过数组第二个参数 Set 一个新值后,原来的值在下次渲染时会形成一个新的引用。2.但它state没有通过this.的方式读取,每次执行都读取当时渲染闭包环境的数据,虽然最新的值跟着最新的渲染变了,但旧的渲染里,状态依然是旧值。)
6.10.3 原理:function组件能捕获渲染的值(captaure the rendered values),读取渲染闭包内的数据,而class组件在react通过this.的方式读取,this是可变的,所以总能获取最新的props。
6.10.4 保存状态:Class把state属性挂载的对象保存到memoizedState属性中,而Function是用链表来保存状态的,memoizedState属性保存是链表的头指针。
6.11 useEffect和useLayoutEffect区别
6.11.1 useEffect是render结束后,callback函数执行,但是不会阻断浏览器的渲染,算是某种异步的方式吧,大部分场景下都比class的同步方式性能更好。
6.11.2 useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否则可能会出现出现闪屏问题, useLayoutEffect里面的callback函数会在DOM更新完成后立即执行,但是会在浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制。
6.12 setState和useState区别 (1.setState是通过回调函数来获取更新的state,useState是通过useEffect() 来获取最新的 state;2.二者第一个参数都可以传入函数;3.setState()可以在第2个参数传入回调,useState()没有第2个参数;4.setState()自动具备浅合并功能,useState()更新引用需要手动浅合并)
6.13 useState中的第二个参数更新状态和class中的this.setState区别 (1.useState 通过数组第二个参数 Set 一个新值后,新值会形成一个新的引用,捕获当时渲染闭包里的数据 State;2.setState 是通过 this.state 的读取 state,每次代码执行都会拿到最新的 state 引用)
6.14 useReducer和redux区别
6.14.1 useReducer() 提供了状态管理,其基本原理是通过用户在页面中发起action, 从而通过 reducer方法来改变state, 从而实现页面和状态的通信,使用很像redux。
6.14.2 useReducer是useState的代替方案,用于state复杂变化
6.14.3 useReducer是单个组件状态管理,组件通讯还需要props,redux是全局的状态管理,多组件共享数据
6.15 Hooks性能优化 (1.useMemo 缓存数据;2.useCallback 缓存函数;3.相当于class组件的SCU和PureComponent)
6.16 怎么在高阶组件里面访问组件实例 (1.属性代理。高阶组件通过包裹的React组件来操作props,更改 props,可以对传递的包裹组件的WrappedComponent的props进行控制。2.通过 refs 获取组件实例。)
7.promise关于宏任务和微任务 (1.主线上的同步任务先执行,然后再执行微任务,最后是宏任务;2.(特殊情况): 一般都是微任务先执行,然后再执行宏任务,但是在promise里面的宏任务函数,必须先执行完,才能往下执行。)
8.redux与react-redux的区别
8.1 简介:(1.redux是react中进行state状态管理的JS库(并不是react插件),一般是管理多个组件中共享数据状态。这个是和Vuex是一样的。2.React-Redux是Redux的官方React绑定库。它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。)
8.2 区别:
8.2.1 redux和组件进行对接的时候是直接在组件中进行创建。react-redux是运用Provider将组件和store对接,使在Provider里的所有组件都能共享store里的数据,还要使用connect将组件和react连接。
8.2.2 获取state的方式不一样;redux获取state是直接通过store.getState()。react-redux获取state是通过mapStateToProps函数,只要state数据变化就能获取最新数据。
8.2.3 触发action的方式不一样;redux是使用dispatch直接触发,来操作store的数据。react-redux是使用mapDispathToProps函数然后在调用dispatch进行触发。
9.简述Redux
9.1 redux主要由三部分组成:store,reducer,action。
9.2 store是一个对象,它有四个主要的方法:dispatch用于action的分发;subscribe监听state的变化;getState获取store中的state;replaceReducer替换reducer,改变state修改的逻辑。
9.3 action是一个对象,其中type属性是必须的,同时可以传入一些数据。action可以用actionCreactor进行创造。dispatch就是把action对象发送出去。
9.4 reducer是一个函数,它接受一个state和一个action,根据action的type返回一个新的state。根据业务逻辑可以分为很多个reducer,然后通过combineReducers将它们合并,state树中有很多对象,每个state对象对应一个reducer,state对象的名字可以在合并时定义。
10.简述http三次握手
10.1 客户端发起一个创建连接的数据包的请求。
10.2 服务端接收到这个数据包。就会开启一个TCP socket的端口,端口开启以后返回给客户端。
10.3 客户端拿到了。继续返回。
10.4 为什么要有三次握手:防止服务端开启无用的连接。因为网络传输是有延时的,可以规避网络延时导致服务器额外的开销。
11.谈一谈闭包
11.1 闭包概念;闭包是指有权访问另外一个函数作用域中的变量的函数.
11.2 闭包应用场景:(1.采用函数引用方式的setTimeout调用,代码:setTimeout(getAge,1000) 2.给对象设置私有变量,并且利用特权去访问私有变量; 3.封装相关功能集)
11.3 闭包引发问题:(1.内存泄漏,解决方法是,在退出函数之前,将不使用的局部变量全部删除;2.this的问题,使用闭包有可能会意外改变this的值。)
12.谈谈原型链
12.1 所有的引用类型(数组、对象、函数)都有一个__proto__属性(也称隐式原型属性),属性值是一个普通的对象;
12.2 所有的函数都有一个prototype属性(也称显式原型属性),属性值也是一个普通的对象;
12.3 所有的引用类型(数组、对象、函数)的__proto__属性(即隐式原型属性)指向它的构造函数的" prototype " 属性值(即显显式原型)(===)
12.4 当调取一个对象的属性时,会先在本身查找,若无,就根据 _proto_ 找到构造原型,若无,继续往上找。最后会到达顶层Object prototype,它的 _proto_ 指向null,均无结果则返回undefined,结束。由 proto 串起的路径就是『原型链』。
13.谈谈React生命周期:
13.1 组件将要挂载时触发的函数:componentWillMount
13.2 组件挂载完成时触发的函数:componentDidMount
13.3 是否要更新数据时触发的函数:shouldComponentUpdate
13.4 将要更新数据时触发的函数:componentWillUpdate
13.5 数据更新完成时触发的函数:componentDidUpdate
13.6 组件将要销毁时触发的函数:componentWillUnmount
13.7 父组件中改变了props传值时触发的函数:componentWillReceiveProps
14.谈谈Vue的数据双向绑定原理
14.1 vue2.0数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。具体通过Object.defineProperty()的 set 和 get,在数据变动时发布消息给订阅者触发监听。结合监听器Observer,订阅者Watcher,解析器Compile实现最终效果。
14.2 vue2.0中的Object.defineProperty缺点:(1.无法监控到数组下标的变化;2.只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历)
14.3 vue3.0用proxy取而代之,两个优点:(1.可以劫持整个对象,并返回一个新对象;2.有13种劫持操作)Proxy的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。
14.4 Proxy是 ES6 中新增的一个特性,翻译过来意思是"代理"。外界对该对象的访问,都必须先通过这层代理拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
15.Vue3.0新特性 (PT组多自优)=>(PT组多自由)
15.1 Proxy 响应式绑定,它劫持的是整个对象,自然对于对象的属性的增加和删除都能检测到。效率更高,性能更好,另外 Virtual DOM 更新只 diff 动态部分、事件缓存等,也带来了性能上的提升。
15.2 Tree-Shaking Support(摇树优化).tree-sharking 即在构建工具构建后消除程序中无用的代码,来减少包的体积。Vue3.0 支持按需导入,只打包需要的代码。
15.3 组合式 API.
15.3.1 组合式API与选项式API,mixins,React Hooks的比较
15.3.1.1 选项式 API 存在的缺陷。Vue2.x 中组件传统的 data,computed,watch,methods 写法,我们称之为选项式API(Options API )务复杂度越来越高,代码量会不断的加大;后续维护非常的复杂;代码可复用性也不高;
15.3.1.2 与 mixins 的比较。(1.层级不同:组合式API与组件是嵌套关系,而mixin与组件是同层级关系;2.影响面不同:组合式API耦合性很低。而 mixins 是耦合在代码逻辑里,升级和维护埋下隐患。)
15.3.1.3 与 React Hook 的比较,React Hooks简便了不少。(1.同样的逻辑组合、组件复用能力。2.只调用一次 setup 方法;3.更加符合 JS 直觉;4.没有闭包变量问题;5.没有内存/GC压力;6.不存在内联回调导致子组件永远更新的问题。)
15.3.2 组合式 API 的使用.
15.3.2.1 setup方法 (1.setup方法,所有的代码逻辑将在setup方法中实现,,包括 data、watchcomputed、methods 等,并且不再有this;2.会先执行setup方法,再执行兼容2.x的其他方法。3.setup方法在组件生命周期内只执行一次,不会重复执行。)
15.3.2.2 生命周期钩子 (1.生命周期钩子放在跟 methods 同级属性下;2.需要先导入钩子,然后在 setup 方法中注册钩子回调,并且钩子命名也跟 React 保持一样;3.移除了 2.x 中的 beforeCreate 和 created 钩子,通过 setup 方法代替)
15.4 多个根节点;Teleport将我们的模板渲染至指定 DOM 节点,不受父级 style 、v-show 等属性影响,但 data、prop 数据依旧能够共用的技术;类似于 React 的 Portal。
<Suspense> 是一个特殊的组件,它将呈现回退内容,而不是对于的组件,直到满足条件为止,这种情况通常是组件 setup 功能中发生的异步操作或者是异步组件中使用。
15.5 自定义渲染 API。通过createRendererAPI 自定义渲染 API 将 Virtual DOM(虚拟DOM)和平台相关的渲染分离。极大丰富了 Vue 的使用场景。
15.6 优化源码
15.6.1 使用 monorepo 来管理源码.(1.Vue.js 2.x 的源码托管在 src 目录,Vue.js 3.0通过 monorepo 的方式根据功能将不同的模块拆分到 packages 目录下面不同的子目录中,每个 package 有各自的 API、类型定义和测试。)
15.632 使用 Typescript 来开发源码.(1.Vue.js 2.x 选用 Flow 做类型检查;2.Vue.js 3.0 使用 TypeScript 重构了整个项目。TypeScript 提供了更好的类型检查,能支持复杂的类型推导;由于源码就使用 TypeScript 编写,也省去了单独维护 d.ts 文件的麻烦)
16.node后端框架选择
16.1 Express是一款基于node.js以及ChromeV8引擎,快速、极简的JS服务端开发框架,它提供了用来开发强壮的web/移动应用,以及API的所有功能。并且开发人员还能够方便地为它开发插件和扩展,从而增加Express的能力。
16.2 KOA框架由Express原班人马打造,它的核心是ES6的generator。KOA使用generator来实现中间件的流程控制,使用try/catch来增强异常处理,KOA框架本身非常小,只打包了一些必要的功能.
16.3 Egg是基于koa,由阿里nodejs团队封装的企业级Web应用解决方案,以约束和规范化团队开发(提供基于Egg定制上层框架的能力;内置多进程管理;渐进式开发。Egg已经被用在阿里多条产品线(包括蚂蚁)上,已经证明它的安全和可靠性,可以放心用。)
16.4 Nest是一个用于构建高效,可扩展的Node.js服务器端应用程序的框架。它使用渐进式javascript,内置并完全支持TypeScript(但仍然允许开发人员使用纯JavaScript编写代码)并结合了OOP(面向对象编程),FP(函数式编程)和FRP(函数式响应编程)的元素。
17.前端工程化方案
17.1 框架选择:(1.后端Nodejs框架:Koa2;2.前端框架: React+Redux;3.CSS处理: Less+Postcss;4.构建工具: Webpack+Babel;5.代码规范: Prettier)
17.2 开发过程:(1.项目初始化:前端脚手架;2.react native方案;3.H5多页应用服务端渲染方案;4.PC 移动端适配方案;5.接口mock服务;6.项目文档)
17.3 优化:(1.http2.0网络优化;2.SSR缓存方案)
17.4 测试:(1.单元测试:Jest+Enzyme;2.生成截图: Chrome Headless)
17.5 运维:(1.性能监控;2.异常报警;3.oss自动上传方案)
18.Web动画实现
18.1 CSS3动画: 书写简单,性能好
18.1.1 transform变形:transform 包含了rotate(旋转)、scale(缩放)、translate(移动)、skew(扭曲)以及matrix(矩阵变形)。一般会结合transition来使用,使元素变形的过程变的平滑。
18.1.2 Transition(过渡):CSS3中的transition是让元素的属性值在一定时间区间内平滑过渡,还可以定义变换速率。
18.1.3 Animation(动画):补间动画是指我们定义好两个时间节点上元素的状态,中间元素变化的过程由计算机帮我们计算好。比如@keyframes swing{ 20%{} 40%{} 60%{} 80%{} to{} }
18.2 JS动画: JS动画一般是通过定时器和计时器来实现元素属性的不断变化,这里一般常用的有jQuery的animate()方法。
18.3 Canvas动画: Canvas动画也是不断的快速的在屏幕上绘制图像和清除屏幕,形成了动画.
18.4 SVG动画:可以学习《SVG精髓》这本书.SVG内置了一些动画元素:animate,animateMotion,animateTransform,animateColor.尽量使用元素属性来进行SVG的动画制作,比如stroke-dasharry,stroke-dashoffset,可以实现描边动画
18.5 Three.js为首的3D动画 Three.js是一个基于JavaScript,使用方便,运行在浏览器中的轻量级的3D框架,可以用它创建各种三维场景,包括摄影机,光影及材质等各种对象,并且提供了Canvas、SVG、CSS 3D及WebGL4中渲染器。
19.响应式布局的核心(@media媒体查询)
19.1 媒体类型:通常我们使用的都是彩色屏幕(screen),打印预览(print),其他的都很少使用.
19.2 媒体属性:
19.2.1 width:浏览器窗口的尺寸(可加max min前缀). min-width:100px >=100px max-width:100px <=100px
19.2.2 height:浏览器窗口的尺寸(可加max min前缀).
19.2.3 device-width:设备独立像素(可加max min前缀).pc端:分辨率.移动端:具体看机器的参数.
19.2.4 device-pixel-ratio:屏幕可见宽度与高度的比率/像素比(可加max min前缀,需要加-webkit前缀). pc端:1; 移动端:具体看机器的参数(DPR).
19.2.5 orientation: portrait(竖屏) | landscape(横屏)
19.3 操作符,关键字(1.only:和浏览器兼容性有关,老版本的浏览器只支持媒体类型,不支持带媒体属性的查询.2.and:代表与的意思,一般用and来连接媒体类型和媒体属性.3.or(,):和and相似.4.not:取反,类似JS里的!.)
20.Web前端性能优化
20.1 内容优化
20.1.1 减少HTTP请求数:这条策略是最重要最有效的,因为一个完整的请求要经过DNS寻址,与服务器建立连接,发送数据,等待服务器响应,接收数据这样一个消耗时间成本和资源成本的复杂的过程。
常见方法:合并多个CSS文件和js文件,利用CSS Sprites整合图像,Inline Images20.1.使用 data:URL scheme在实际的页面嵌入图像数据 ,合理设置HTTP缓存等。
20.1.2 减少DNS查找
20.1.3 避免重定向
20.1.4 延迟加载组件,预加载组件
20.1.5 减少DOM元素数量:页面中存在大量DOM元素,会导致javascript遍历DOM的效率变慢。
20.1.6 最小化iframe的数量:iframes 提供了一个简单的方式把一个网站的内容嵌入到另一个网站中。但其创建速度比其他包括JavaScript和CSS的DOM元素的创建慢了1-2个数量级。
20.1.7 避免404:HTTP请求时间消耗是很大的,因此使用HTTP请求来获得一个没有用处的响应(例如404没有找到页面)是完全没有必要的,它只会降低用户体验而不会有一点好处。
20.2 服务器优化
20.2.1 使用内容分发网络(CDN):把网站内容分散到多个、处于不同地域位置的服务器上可以加快下载速度。
20.2.2 GZIP压缩
20.2.3 设置ETag:ETags(Entity tags,实体标签)是web服务器和浏览器用于判断浏览器缓存中的内容和服务器中的原始内容是否匹配的一种机制。
20.2.4 提前刷新缓冲区
20.2.5 避免空的图像src
20.3 Cookie优化
20.3.1 减小Cookie大小
20.3.2 针对Web组件使用域名无关的Cookie
20.4 CSS优化
20.4.1 将CSS代码放在HTML页面的顶部
20.4.2 避免使用CSS表达式
20.4.3 使用<link>来代替@import
20.5 javascript优化
20.5.1 将JavaScript脚本放在页面的底部。
20.5.2 将JavaScript和CSS作为外部文件来引用:在实际应用中使用外部文件可以提高页面速度,因为JavaScript和CSS文件都能在浏览器中产生缓存。
20.5.3 缩小JavaScript和CSS
20.5.4 删除重复的脚本
20.5.5 最小化DOM的访问:使用JavaScript访问DOM元素比较慢。
20.5.6 开发智能的事件处理程序
20.5.7 javascript代码注意:谨慎使用with,避免使用eval Function函数,减少作用域链查找。
20.6 图像优化
20.6.1 优化图片大小
20.6.2 通过CSS Sprites优化图片
20.6.3 不要在HTML中使用缩放图片
20.6.4 favicon.ico要小而且可缓存
21.DNS解析过程
21.1 先检查本地 hosts 文件中是否有映射,有则使用;
21.2 查找本地 DNS 缓存,有则返回;
21.3 根据配置在 TCP/IP 参数中设置 DNS 查询服务器,并向其进行查询,这里先称为本地 DNS;
21.4 如果该服务器无法解析域名(没有缓存),且不需要转发,则会向根服务器请求;
21.5 根服务器根据域名类型判断对应的顶级域名服务器(.com),返回给本地 DNS,然后重复该过程,直到找到该域名;
备注:当然,如果设置了转发,本地 DNS 会将请求逐级转发,直到转发服务器返回或者也不能解析。
结论:所以减少DNS的查询次数非常重要,页面加载时就尽量避免额外耗时。为了减少DNS的询次数,最好的解决方法就是在页面中减少不同的域名请求的机会。
22.JS新特性
22.1 ES2015(ES6)(let、const关键字;箭头函数;class 类;模块(import/export);模板语法;函数参数默认值;rest参数;数组/对象 解构;Promise)
22.2 ES2016(ES7) ES7在ES6的基础上主要扩展了一些数组的方法例如.includes(),还有指数运算符**
22.3 ES2017(ES8) ES8添加了关键字async/await,让处理异步程序更加方便。我们能够通过使用它避免面条代码,提高异步代码的可读性.
22.4 ES2018(ES9) ES9没有增加新的东西,但是增强了rest和扩展运算符。(const {enabled, ...others} = options;)(const param = {enabled: true, ...options})
22.5 ES2019(ES10) ES10让使用try/catch更加简单,不需要声明一个Error然后去捕获他。这对不需要知道抛出的错误是什么的场景可能有些帮助。
22.6 ES2020(ES11) 1.动态引入,减少包体积;2.BigInt;3.控制合并运算符??(取模);4.可选链?.。
1.两边固定,中间自适应布局(1.用flex;2.用display:left;3.用相对定位和绝对定位结合)
2.js判断字符串中出现次数最多的字符(1.用for循环将字符串字符和出现次数push到一个新对象中;2.在这个新对象中用for in进行比较,分别找出次数最多的字符和出现次数。)
3.Vue.set的用法及场景(1.vue中检测不到对象属性的添加和删除;2.通过数组的下标去修改数组的值,数据已经被修改了,但是不触发updated函数,视图不更新。原理:vue.$set是能让vue知道你添加了属性, 它会给你做处理。)
4.Vue自定义指令的钩子函数及使用场景
4.1 钩子函数:bind,inserted,update,componentUpdated,unbind)
4.2 函数参数:el,binding,vnode,oldVnode
4.3 使用场景:按钮级别的权限控制
5.Vue页面渲染过程 (
5.1 加载文件执行顺序:1.打包配置位置;2.index.html;3.main.js;4.路由文件,将组件渲染到router-view;5.router-view中加载layout;6.Layout加载Navbar,Sidebar,AppMain
5.2 Vue内部页面执行顺序:1.把模板编译为render函数;2.实例进行挂载,根据根节点render函数的调用,递归生成虚拟DOM;3.对比虚拟DOM,渲染到真实DOM;4.组件内部发生变化,data作为props重新调用render函数,生成虚拟DOM,重复第3步.
6.React Hooks
6.1 为何用hooks(1.组件之间的逻辑状态难以复用;2.大型复杂组件难以拆分;3.Class语法的使用不友好)
6.2 hooks优点(1.没有破坏性改动,完全可选;2.更容易复用代码,复用状态;3.函数式编程风格,清爽优雅;4.代码量少;5.更容易拆分)
6.3 hooks缺点 (1.是React16.8版本的新增特性;2.因为闭包造成状态不同步;3.数组的push,pop,splice方法直接改变原数组,使用useState无法获取更新;4.useState初始化只初始化一次;5.useEffect内部不能修改state;6.useEffect依赖引用类型会出现死循环;7.不要在循环,嵌套,条件函数中调用hook,会产生顺序不一致问题)
6.4 解决闭包的坑 (闭包造成每次输出原来的state。可以通过useRef来保存state)
6.5 常用的Hooks有哪些 (1.useState()状态钩子;2.useContext()共享状态钩子;3.useReducer()状态钩子,很像redux;4.useEffect()副作用钩子,两个参数,一个是异步操作,一个是数组依赖项;5.useRef()获取组件实例,渲染周期之间共享数据的存储;6.useMemo缓存数据,useCallback缓存函数,常见的优化策略)
useCallback(fn,deps)相当于useMemo(()=>fn,deps),经常用在下面两种场景:
6.5.1 要保持引用相等;对于组件内部用到的 object、array、函数等
6.5.2 用在了其他 Hook 的依赖数组中,或者作为 props 传递给了下游组件,应该使用 useMemo/useCallback)
6.6 useEffect为什么有时候会出现无限重复请求的问题 (可能1.未设置依赖参数,每渲染一次就触发一次;可能2.所设置的依赖项总是会变。解决:useCallback包一层,或者useMemo)
6.7 使用hooks模拟生命周期 (可以封装一个模拟的js,然后各处都可以调用)
6.7.1 使用useState模拟constructor 代码:const [count, setCount] = useState(0)
6.7.2 使用useEffect模拟componentDidMount 代码:useEffect(() => { fn() }, [])
6.7.3 使用useMemo模拟shouldComponentUpdate 代码:React.useMemo((props) => {// your component})
6.7.4 使用useEffect+useState模拟componentDidUpdata 代码:useEffect(() => fn() ));
6.7.5 使用useEffect模拟componentUnMount 代码:useEffect(() => fn(), [])
6.8 模拟的生命周期和class中的生命周期有什么区别 (1.默认的useEffect(不带[])中return的清理函数,默认情况下在每次useEffect执行前都会执行,并不是只有组件卸载的时候执行; 2.useEffect在副作用结束之后,会延迟一段时间执行,并非同步,和compontDidMount有本质区别。遇到dom操作,最好使用useLayoutEffect。)
6.9 Hooks相比HOC和Render Prop有哪些优点?(1.hoc和render prop都是一种开发模式,将复用逻辑提升到父组件,容易嵌套过多,过度包装;2.hooks是react的api模式,将复用逻辑取到组件顶层,能够避免 HOC 和 Render Props 带来的「嵌套地狱」。)
6.10 Function Component与Class Component区别
6.10.1 对于class component来说:(1.首先state是不可变(Immutable),setState后生成一个全新的state引用;2.通过this.state方式读取state,所以每次代码执行都会拿到最新的state引用。)
6.10.2 对于function component来说:(1.useState 产生的数据也是不可变 Immutable 的,通过数组第二个参数 Set 一个新值后,原来的值在下次渲染时会形成一个新的引用。2.但它state没有通过this.的方式读取,每次执行都读取当时渲染闭包环境的数据,虽然最新的值跟着最新的渲染变了,但旧的渲染里,状态依然是旧值。)
6.10.3 原理:function组件能捕获渲染的值(captaure the rendered values),读取渲染闭包内的数据,而class组件在react通过this.的方式读取,this是可变的,所以总能获取最新的props。
6.10.4 保存状态:Class把state属性挂载的对象保存到memoizedState属性中,而Function是用链表来保存状态的,memoizedState属性保存是链表的头指针。
6.11 useEffect和useLayoutEffect区别
6.11.1 useEffect是render结束后,callback函数执行,但是不会阻断浏览器的渲染,算是某种异步的方式吧,大部分场景下都比class的同步方式性能更好。
6.11.2 useEffect里面的操作需要处理DOM,并且会改变页面的样式,就需要用这个,否则可能会出现出现闪屏问题, useLayoutEffect里面的callback函数会在DOM更新完成后立即执行,但是会在浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制。
6.12 setState和useState区别 (1.setState是通过回调函数来获取更新的state,useState是通过useEffect() 来获取最新的 state;2.二者第一个参数都可以传入函数;3.setState()可以在第2个参数传入回调,useState()没有第2个参数;4.setState()自动具备浅合并功能,useState()更新引用需要手动浅合并)
6.13 useState中的第二个参数更新状态和class中的this.setState区别 (1.useState 通过数组第二个参数 Set 一个新值后,新值会形成一个新的引用,捕获当时渲染闭包里的数据 State;2.setState 是通过 this.state 的读取 state,每次代码执行都会拿到最新的 state 引用)
6.14 useReducer和redux区别
6.14.1 useReducer() 提供了状态管理,其基本原理是通过用户在页面中发起action, 从而通过 reducer方法来改变state, 从而实现页面和状态的通信,使用很像redux。
6.14.2 useReducer是useState的代替方案,用于state复杂变化
6.14.3 useReducer是单个组件状态管理,组件通讯还需要props,redux是全局的状态管理,多组件共享数据
6.15 Hooks性能优化 (1.useMemo 缓存数据;2.useCallback 缓存函数;3.相当于class组件的SCU和PureComponent)
6.16 怎么在高阶组件里面访问组件实例 (1.属性代理。高阶组件通过包裹的React组件来操作props,更改 props,可以对传递的包裹组件的WrappedComponent的props进行控制。2.通过 refs 获取组件实例。)
7.promise关于宏任务和微任务 (1.主线上的同步任务先执行,然后再执行微任务,最后是宏任务;2.(特殊情况): 一般都是微任务先执行,然后再执行宏任务,但是在promise里面的宏任务函数,必须先执行完,才能往下执行。)
8.redux与react-redux的区别
8.1 简介:(1.redux是react中进行state状态管理的JS库(并不是react插件),一般是管理多个组件中共享数据状态。这个是和Vuex是一样的。2.React-Redux是Redux的官方React绑定库。它能够使你的React组件从Redux store中读取数据,并且向store分发actions以更新数据。)
8.2 区别:
8.2.1 redux和组件进行对接的时候是直接在组件中进行创建。react-redux是运用Provider将组件和store对接,使在Provider里的所有组件都能共享store里的数据,还要使用connect将组件和react连接。
8.2.2 获取state的方式不一样;redux获取state是直接通过store.getState()。react-redux获取state是通过mapStateToProps函数,只要state数据变化就能获取最新数据。
8.2.3 触发action的方式不一样;redux是使用dispatch直接触发,来操作store的数据。react-redux是使用mapDispathToProps函数然后在调用dispatch进行触发。
9.简述Redux
9.1 redux主要由三部分组成:store,reducer,action。
9.2 store是一个对象,它有四个主要的方法:dispatch用于action的分发;subscribe监听state的变化;getState获取store中的state;replaceReducer替换reducer,改变state修改的逻辑。
9.3 action是一个对象,其中type属性是必须的,同时可以传入一些数据。action可以用actionCreactor进行创造。dispatch就是把action对象发送出去。
9.4 reducer是一个函数,它接受一个state和一个action,根据action的type返回一个新的state。根据业务逻辑可以分为很多个reducer,然后通过combineReducers将它们合并,state树中有很多对象,每个state对象对应一个reducer,state对象的名字可以在合并时定义。
10.简述http三次握手
10.1 客户端发起一个创建连接的数据包的请求。
10.2 服务端接收到这个数据包。就会开启一个TCP socket的端口,端口开启以后返回给客户端。
10.3 客户端拿到了。继续返回。
10.4 为什么要有三次握手:防止服务端开启无用的连接。因为网络传输是有延时的,可以规避网络延时导致服务器额外的开销。
11.谈一谈闭包
11.1 闭包概念;闭包是指有权访问另外一个函数作用域中的变量的函数.
11.2 闭包应用场景:(1.采用函数引用方式的setTimeout调用,代码:setTimeout(getAge,1000) 2.给对象设置私有变量,并且利用特权去访问私有变量; 3.封装相关功能集)
11.3 闭包引发问题:(1.内存泄漏,解决方法是,在退出函数之前,将不使用的局部变量全部删除;2.this的问题,使用闭包有可能会意外改变this的值。)
12.谈谈原型链
12.1 所有的引用类型(数组、对象、函数)都有一个__proto__属性(也称隐式原型属性),属性值是一个普通的对象;
12.2 所有的函数都有一个prototype属性(也称显式原型属性),属性值也是一个普通的对象;
12.3 所有的引用类型(数组、对象、函数)的__proto__属性(即隐式原型属性)指向它的构造函数的" prototype " 属性值(即显显式原型)(===)
12.4 当调取一个对象的属性时,会先在本身查找,若无,就根据 _proto_ 找到构造原型,若无,继续往上找。最后会到达顶层Object prototype,它的 _proto_ 指向null,均无结果则返回undefined,结束。由 proto 串起的路径就是『原型链』。
13.谈谈React生命周期:
13.1 组件将要挂载时触发的函数:componentWillMount
13.2 组件挂载完成时触发的函数:componentDidMount
13.3 是否要更新数据时触发的函数:shouldComponentUpdate
13.4 将要更新数据时触发的函数:componentWillUpdate
13.5 数据更新完成时触发的函数:componentDidUpdate
13.6 组件将要销毁时触发的函数:componentWillUnmount
13.7 父组件中改变了props传值时触发的函数:componentWillReceiveProps
14.谈谈Vue的数据双向绑定原理
14.1 vue2.0数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。具体通过Object.defineProperty()的 set 和 get,在数据变动时发布消息给订阅者触发监听。结合监听器Observer,订阅者Watcher,解析器Compile实现最终效果。
14.2 vue2.0中的Object.defineProperty缺点:(1.无法监控到数组下标的变化;2.只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历)
14.3 vue3.0用proxy取而代之,两个优点:(1.可以劫持整个对象,并返回一个新对象;2.有13种劫持操作)Proxy的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。
14.4 Proxy是 ES6 中新增的一个特性,翻译过来意思是"代理"。外界对该对象的访问,都必须先通过这层代理拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
15.Vue3.0新特性 (PT组多自优)=>(PT组多自由)
15.1 Proxy 响应式绑定,它劫持的是整个对象,自然对于对象的属性的增加和删除都能检测到。效率更高,性能更好,另外 Virtual DOM 更新只 diff 动态部分、事件缓存等,也带来了性能上的提升。
15.2 Tree-Shaking Support(摇树优化).tree-sharking 即在构建工具构建后消除程序中无用的代码,来减少包的体积。Vue3.0 支持按需导入,只打包需要的代码。
15.3 组合式 API.
15.3.1 组合式API与选项式API,mixins,React Hooks的比较
15.3.1.1 选项式 API 存在的缺陷。Vue2.x 中组件传统的 data,computed,watch,methods 写法,我们称之为选项式API(Options API )务复杂度越来越高,代码量会不断的加大;后续维护非常的复杂;代码可复用性也不高;
15.3.1.2 与 mixins 的比较。(1.层级不同:组合式API与组件是嵌套关系,而mixin与组件是同层级关系;2.影响面不同:组合式API耦合性很低。而 mixins 是耦合在代码逻辑里,升级和维护埋下隐患。)
15.3.1.3 与 React Hook 的比较,React Hooks简便了不少。(1.同样的逻辑组合、组件复用能力。2.只调用一次 setup 方法;3.更加符合 JS 直觉;4.没有闭包变量问题;5.没有内存/GC压力;6.不存在内联回调导致子组件永远更新的问题。)
15.3.2 组合式 API 的使用.
15.3.2.1 setup方法 (1.setup方法,所有的代码逻辑将在setup方法中实现,,包括 data、watchcomputed、methods 等,并且不再有this;2.会先执行setup方法,再执行兼容2.x的其他方法。3.setup方法在组件生命周期内只执行一次,不会重复执行。)
15.3.2.2 生命周期钩子 (1.生命周期钩子放在跟 methods 同级属性下;2.需要先导入钩子,然后在 setup 方法中注册钩子回调,并且钩子命名也跟 React 保持一样;3.移除了 2.x 中的 beforeCreate 和 created 钩子,通过 setup 方法代替)
15.4 多个根节点;Teleport将我们的模板渲染至指定 DOM 节点,不受父级 style 、v-show 等属性影响,但 data、prop 数据依旧能够共用的技术;类似于 React 的 Portal。
<Suspense> 是一个特殊的组件,它将呈现回退内容,而不是对于的组件,直到满足条件为止,这种情况通常是组件 setup 功能中发生的异步操作或者是异步组件中使用。
15.5 自定义渲染 API。通过createRendererAPI 自定义渲染 API 将 Virtual DOM(虚拟DOM)和平台相关的渲染分离。极大丰富了 Vue 的使用场景。
15.6 优化源码
15.6.1 使用 monorepo 来管理源码.(1.Vue.js 2.x 的源码托管在 src 目录,Vue.js 3.0通过 monorepo 的方式根据功能将不同的模块拆分到 packages 目录下面不同的子目录中,每个 package 有各自的 API、类型定义和测试。)
15.632 使用 Typescript 来开发源码.(1.Vue.js 2.x 选用 Flow 做类型检查;2.Vue.js 3.0 使用 TypeScript 重构了整个项目。TypeScript 提供了更好的类型检查,能支持复杂的类型推导;由于源码就使用 TypeScript 编写,也省去了单独维护 d.ts 文件的麻烦)
16.node后端框架选择
16.1 Express是一款基于node.js以及ChromeV8引擎,快速、极简的JS服务端开发框架,它提供了用来开发强壮的web/移动应用,以及API的所有功能。并且开发人员还能够方便地为它开发插件和扩展,从而增加Express的能力。
16.2 KOA框架由Express原班人马打造,它的核心是ES6的generator。KOA使用generator来实现中间件的流程控制,使用try/catch来增强异常处理,KOA框架本身非常小,只打包了一些必要的功能.
16.3 Egg是基于koa,由阿里nodejs团队封装的企业级Web应用解决方案,以约束和规范化团队开发(提供基于Egg定制上层框架的能力;内置多进程管理;渐进式开发。Egg已经被用在阿里多条产品线(包括蚂蚁)上,已经证明它的安全和可靠性,可以放心用。)
16.4 Nest是一个用于构建高效,可扩展的Node.js服务器端应用程序的框架。它使用渐进式JavaScript,内置并完全支持TypeScript(但仍然允许开发人员使用纯JavaScript编写代码)并结合了OOP(面向对象编程),FP(函数式编程)和FRP(函数式响应编程)的元素。
17.前端工程化方案
17.1 框架选择:(1.后端Nodejs框架:Koa2;2.前端框架: React+Redux;3.CSS处理: Less+Postcss;4.构建工具: Webpack+Babel;5.代码规范: Prettier)
17.2 开发过程:(1.项目初始化:前端脚手架;2.react native方案;3.H5多页应用服务端渲染方案;4.PC 移动端适配方案;5.接口mock服务;6.项目文档)
17.3 优化:(1.http2.0网络优化;2.SSR缓存方案)
17.4 测试:(1.单元测试:Jest+Enzyme;2.生成截图: Chrome Headless)
17.5 运维:(1.性能监控;2.异常报警;3.oss自动上传方案)
18.Web动画实现
18.1 CSS3动画: 书写简单,性能好
18.1.1 transform变形:transform 包含了rotate(旋转)、scale(缩放)、translate(移动)、skew(扭曲)以及matrix(矩阵变形)。一般会结合transition来使用,使元素变形的过程变的平滑。
18.1.2 Transition(过渡):CSS3中的transition是让元素的属性值在一定时间区间内平滑过渡,还可以定义变换速率。
18.1.3 Animation(动画):补间动画是指我们定义好两个时间节点上元素的状态,中间元素变化的过程由计算机帮我们计算好。比如@keyframes swing{ 20%{} 40%{} 60%{} 80%{} to{} }
18.2 JS动画: JS动画一般是通过定时器和计时器来实现元素属性的不断变化,这里一般常用的有jQuery的animate()方法。
18.3 Canvas动画: Canvas动画也是不断的快速的在屏幕上绘制图像和清除屏幕,形成了动画.
18.4 SVG动画:可以学习《SVG精髓》这本书.SVG内置了一些动画元素:animate,animateMotion,animateTransform,animateColor.尽量使用元素属性来进行SVG的动画制作,比如stroke-dasharry,stroke-dashoffset,可以实现描边动画
18.5 Three.js为首的3D动画 Three.js是一个基于JavaScript,使用方便,运行在浏览器中的轻量级的3D框架,可以用它创建各种三维场景,包括摄影机,光影及材质等各种对象,并且提供了Canvas、SVG、CSS 3D及WebGL4中渲染器。
19.响应式布局的核心(@media媒体查询)
19.1 媒体类型:通常我们使用的都是彩色屏幕(screen),打印预览(print),其他的都很少使用.
19.2 媒体属性:
19.2.1 width:浏览器窗口的尺寸(可加max min前缀). min-width:100px >=100px max-width:100px <=100px
19.2.2 height:浏览器窗口的尺寸(可加max min前缀).
19.2.3 device-width:设备独立像素(可加max min前缀).pc端:分辨率.移动端:具体看机器的参数.
19.2.4 device-pixel-ratio:屏幕可见宽度与高度的比率/像素比(可加max min前缀,需要加-webkit前缀). pc端:1; 移动端:具体看机器的参数(DPR).
19.2.5 orientation: portrait(竖屏) | landscape(横屏)
19.3 操作符,关键字(1.only:和浏览器兼容性有关,老版本的浏览器只支持媒体类型,不支持带媒体属性的查询.2.and:代表与的意思,一般用and来连接媒体类型和媒体属性.3.or(,):和and相似.4.not:取反,类似JS里的!.)
20.Web前端性能优化
20.1 内容优化
20.1.1 减少HTTP请求数:这条策略是最重要最有效的,因为一个完整的请求要经过DNS寻址,与服务器建立连接,发送数据,等待服务器响应,接收数据这样一个消耗时间成本和资源成本的复杂的过程。
常见方法:合并多个CSS文件和js文件,利用CSS Sprites整合图像,Inline Images20.1.使用 data:URL scheme在实际的页面嵌入图像数据 ,合理设置HTTP缓存等。
20.1.2 减少DNS查找
20.1.3 避免重定向
20.1.4 延迟加载组件,预加载组件
20.1.5 减少DOM元素数量:页面中存在大量DOM元素,会导致javascript遍历DOM的效率变慢。
20.1.6 最小化iframe的数量:iframes 提供了一个简单的方式把一个网站的内容嵌入到另一个网站中。但其创建速度比其他包括JavaScript和CSS的DOM元素的创建慢了1-2个数量级。
20.1.7 避免404:HTTP请求时间消耗是很大的,因此使用HTTP请求来获得一个没有用处的响应(例如404没有找到页面)是完全没有必要的,它只会降低用户体验而不会有一点好处。
20.2 服务器优化
20.2.1 使用内容分发网络(CDN):把网站内容分散到多个、处于不同地域位置的服务器上可以加快下载速度。
20.2.2 GZIP压缩
20.2.3 设置ETag:ETags(Entity tags,实体标签)是web服务器和浏览器用于判断浏览器缓存中的内容和服务器中的原始内容是否匹配的一种机制。
20.2.4 提前刷新缓冲区
20.2.5 避免空的图像src
20.3 Cookie优化
20.3.1 减小Cookie大小
20.3.2 针对Web组件使用域名无关的Cookie
20.4 CSS优化
20.4.1 将CSS代码放在HTML页面的顶部
20.4.2 避免使用CSS表达式
20.4.3 使用<link>来代替@import
20.5 javascript优化
20.5.1 将JavaScript脚本放在页面的底部。
20.5.2 将JavaScript和CSS作为外部文件来引用:在实际应用中使用外部文件可以提高页面速度,因为JavaScript和CSS文件都能在浏览器中产生缓存。
20.5.3 缩小JavaScript和CSS
20.5.4 删除重复的脚本
20.5.5 最小化DOM的访问:使用JavaScript访问DOM元素比较慢。
20.5.6 开发智能的事件处理程序
20.5.7 javascript代码注意:谨慎使用with,避免使用eval Function函数,减少作用域链查找。
20.6 图像优化
20.6.1 优化图片大小
20.6.2 通过CSS Sprites优化图片
20.6.3 不要在HTML中使用缩放图片
20.6.4 favicon.ico要小而且可缓存
21.DNS解析过程
21.1 先检查本地 hosts 文件中是否有映射,有则使用;
21.2 查找本地 DNS 缓存,有则返回;
21.3 根据配置在 TCP/IP 参数中设置 DNS 查询服务器,并向其进行查询,这里先称为本地 DNS;
21.4 如果该服务器无法解析域名(没有缓存),且不需要转发,则会向根服务器请求;
21.5 根服务器根据域名类型判断对应的顶级域名服务器(.com),返回给本地 DNS,然后重复该过程,直到找到该域名;
备注:当然,如果设置了转发,本地 DNS 会将请求逐级转发,直到转发服务器返回或者也不能解析。
结论:所以减少DNS的查询次数非常重要,页面加载时就尽量避免额外耗时。为了减少DNS的询次数,最好的解决方法就是在页面中减少不同的域名请求的机会。
22.JS新特性
22.1 ES2015(ES6)(let、const关键字;箭头函数;class 类;模块(import/export);模板语法;函数参数默认值;rest参数;数组/对象 解构;Promise)
22.2 ES2016(ES7) ES7在ES6的基础上主要扩展了一些数组的方法例如.includes(),还有指数运算符**
22.3 ES2017(ES8) ES8添加了关键字async/await,让处理异步程序更加方便。我们能够通过使用它避免面条代码,提高异步代码的可读性.
22.4 ES2018(ES9) ES9没有增加新的东西,但是增强了rest和扩展运算符。(const {enabled, ...others} = options;)(const param = {enabled: true, ...options})
22.5 ES2019(ES10) ES10让使用try/catch更加简单,不需要声明一个Error然后去捕获他。这对不需要知道抛出的错误是什么的场景可能有些帮助。
22.6 ES2020(ES11) 1.动态引入,减少包体积;2.BigInt;3.控制合并运算符??(取模);4.可选链?.。
以上是关于2021年高级前端进阶之路的主要内容,如果未能解决你的问题,请参考以下文章