文章目录
- 1. 函数柯里化
- 2. get和post的差别
- @不熟 3. request payload 和 form data之间的区别
- 4. HTTP、HTTPs协议详细介绍
- 5.v8引擎的AST是什么
- 6.BFC
- 7.文档流
- 8.布局方案
- 9.浏览器从发出请求到接受响应,中间过程
- 10.前端存储
- 11.vite和webpack的区别
- 12.状态管理存储 , localstorage
- @不熟 13.H5新特新:Web Worker、WebSocket
- 14.Vue 生命周期的理解
- 15.谈一谈对 MVVM 的理解?
- 16.Vue 实现双向数据绑定的原理?
- 17.Vue2.x 中如何检测数组的变化?
- 不熟@ 18.vue2.x 和 vuex3.x 渲染器的 diff 算法分别说一下?
- 19.Vue 的路由实现
- 20.vuex和pina的区别?
- 21.`nextTick` 的作用是什么?他的实现原理是什么?
- 22.热更新
- 23.服务端渲染(SSR)
- 24.react-hooks
- 25.redux
- 26.call、apply、bind的作用和区别
- 27.this指向
- 28.垃圾回收机制
- 29.EventLoop(事件循环)
- 30.内存溢出和内存泄漏
1. 函数柯里化
- 使用:固定部分参数,返回接收剩余参数的函数,
- 目的:建一个针对性更强的函数
- 核心思想:把多参数传入的函数,拆成一个个的单参数的函数,内部再返回调用下一个单(或部分)参数的函数,依次处理剩余参数
// 柯里化前
const log = (date, project, message) => {
return `${date} ${project} ${message}`
}
//输出2022-07-29 xxx后台管理系统 mm接口异常
console.log(log('2022-07-29', 'xxx后台管理系统', 'mm接口异常'))
//柯里化后
const log = (date) => {
return (projectName) => {
return (message) => {
return `${date} ${projectName} ${message}`
}
}
}
//那个参数固定,则传入同一个参数,只改要变的参数
console.log(log('2022-07-29')('A项目')('接口报错'));
2. get和post的差别
- 参数:get通过拼接url进行参数传递,参数可见;post通过请求头传递参数,参数不可见
- 数据携带量:get请求携带的数据不超过2~4k,(浏览器不同,携带量不同,但相差不大);post请求携带量根据配置文件设定,无上限
- 后退页面的反应: 页面后退,get请求无影响,post请求需要重新提交请求
- 缓存性:get请求可以缓存,post请求不可缓存
- 传输速度:get比post更快。(get产生一个TCP数据包;post产生两个TCP数据包)
- 安全性:原则上post更安全,因为post的数据在url上不可见
@不熟 3. request payload 和 form data之间的区别
- FormData和Payload是浏览器传输给接口的两种格式,这两种方式浏览器是通过Content-Type来进行区分的。
- Content-Type是指 HTTP 请求发送信息至服务器时的内容编码类型
- RequestPayload是(HTTP请求体模式),FormData是(表单请求体模式)
4. HTTP、HTTPs协议详细介绍
1. HTTP协议详细信息
- HTTP(超文本传输协议),是一种详细规定了浏览器和万维网服务器之间相互通信的规则,通过因特网传送万维网文档的数据传输协议
- HTTP是基于TCP/IP的应用层协议
- HTTP不仅能应用于网页浏览,只要通信双方都遵守HTTP协议,都能使用HTTP协议
2. HTTP协议的特点
- 简单快速:只需传送请求方法和路径
- 灵活:允许传输任意类型数据对象
- 无状态:指协议对于事件处理没有记忆能力,缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
- 支持B/S、C/S模式
3. HTTP工作流程
- 浏览器与服务器建立连接
- 浏览器向服务器发送请求
- 服务器接收请求,
- 向浏览器返回响应
- 浏览器接收到响应,渲染页面
- 断开与服务器的连接
4. HTTP协议请求方式(共8种)
HTTP 1.0 定义了三种(get、post、head)
get:获取,一般用于查询数据,在处理敏感数据时不用,或者参数做加密处理。请求参数拼接在url里
post:一般用于修改数据,数据发送到服务器以创建或更新资源,侧重于更新数据。请求参数在请求body中
head:head方法与get方法相同,但没有响应体,仅传输状态行和标题部分。这对于恢复相应头部编写的元数据非常有用,而无需传输整个内容。
HTTP 1.1 新增了6种(put、delete、pacth、options、trace、connect)
put:一般用于新增数据,数据发送到服务器以创建或更新资源,侧重于创建数据
delete:一般用于删除数据,用来删除指定的资源,它会删除URI给出的目标资源的所有当前内容
pacth:用于资源的部分内容的更新;会在资源不存在时去创建它(有则修改,无则添加)
options:用来描述了目标资源的通信选项,返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送`*`的请求来测试服务器的功能性
trace:用于沿着目标资源的路径执行消息环回测试;它回应收到的请求,以便客户可以看到中间服务器进行了哪些(假设任何)进度或增量。
connect:用来建立到给定URI标识的服务器的隧道;它通过简单的TCP / IP隧道更改请求连接,通常是使用解码的HTTP代理来进行SSL编码的通信(HTTPS)
5.HTTP协议状态码
100~199: 提供信息。
200~299: 请求被成功提交。
300~399: 客户端被重定向到其他资源。
400~499: 请求包含某种错误。
500~599: 服务器执行请求时遇到错误。
6.HTTPS
- 与http的区别:安全性比http高,是HTTP 的安全版
- 主要作用:建立一个信息安全通道,来确保数据的传输,确保网站的真实性
- 优点:确保数据发送到正确的客户端和服务器,确保数据的完整性,大幅度增加了中间人攻击的成本
- 缺点:增大了与服务器握手时间(大约增加了50%),SSL证书需要收费
5.v8引擎的AST是什么
- V8引擎是使用AST(抽象语法树)来解析和转换js代码的
- AST是解析和转换JavaScript代码的树状结构表示,它提供了一种便捷的方式来分析、修改和转换代码。
6.BFC
- BFC是块级格式化上下文,可以把BFC看成一个容器,容器内的元素不会影响到外部元素
- BFC的特性
1. BFC是块级元素,在垂直方向上依次排列
2. BFC是独立容器,内部元素不会影响到外部元素
3. 同一个BFC里面的两个盒子,外边距会发生重叠,并取最大外边距
4. 计算BFC高度时,浮动元素也要参与计算
- 创建BFC
1. overflow:hidden 隐藏的内容
2. display:flex 转变为弹性盒子,变现为块级元素
3. position:abssolute 绝对定位
4. position:fixed 固定定位
5. display:inline-flex 转变为弹性盒子,变现为行内块元素
6. display:inline-block 转变为行内块元素
- BFC的作用:
1. 解决父元素未设置高度,子元素浮动造成父元素高度塌陷的问题
2. 解决子元素外边距错误的加到父元素上的问题
7.文档流
CSS 有三种基本的定位机制:普通流、浮动流、定位流。
文档流(标准流、普通流)
- html的默认排版方式
- 特点:块级元素上下排列,行内块元素、行内元素左右排列
浮动流
- 脱离标准流的排版方式,使用float:none/left/right实现
- 特点:
1. 浮动后的元素只有居左、居右、无三种属性,
2. 浮动后的元素可以设置宽高
3. 元素只在父元素宽高范围内浮动
4. 浮动后的元素不可使用margin:0 auto;
5. 元素浮动后,后面的同级元素会占据他原本的位置
6. 如果两个浮动的元素的宽之和小于父元素宽,左右排列
7. 如果两个浮动的元素的宽之和大于父元素宽,上下排列
定位流
- 定位分为相对定位、绝对定位、固定定位、静态定位(文档流默认定位)
- 相对定位不脱离文档流,绝对定位、固定定位会脱离文档流
- z-index属性是专门控制定位流元素的覆盖关系
8.布局方案
- 居中布局(水平居中、垂直居中、水平垂直居中)
- 双飞翼布局(侧边两栏宽度固定,中间栏宽度自适应)
- 圣杯布局(侧边两栏宽度固定,中间栏宽度自适应)
- 栅格布局
9.浏览器从发出请求到接受响应,中间过程
1. 用户输入url,生成http请求
2. 解析域名,得到IP地址。(根据url域名从本地hosts文件查找是否有映射IP,如果查找不到,则将域名发送给电脑所配置的DNS进行域名解析,得到IP地址)
3. 建立TCP连接(三次握手)
4. 向服务器发送HTTP请求
5. 服务器收到请求
6. servlet处理请求
7. 将响应结果封装成 HTTP 响应的格式,发送给浏览器,关闭TCP连接,请求响应完成
8. 浏览器收到响应数据,解析并渲染响应页面
10.前端存储
优势
- 方便网页加载,避免了在发送请求收到响应前的空白期
- 减少向服务器的请求次数,加快渲染速度
- 在网络不佳或无网络时,也可以离线浏览网页
存储方式
分为存储类(cookie、localStroage、sessionStroage)、缓存类(Cache Storage、Application Cache)
存储类
1、2. Web Storage(localStorage、sessionStorage)
HTML5提出的存储方式,容量5M
优点:
1. 克服了cookie的限制,同时存储一些要严格控制在客户端,不需要发送给服务器的数据
2. 提供了除cookie之外的存储会话途径
3. 存储容量大,跨会话存储数据
localStorage:
1. 永久存储,除非自动删除
2. 保存在客户端,不与服务器进行交互通信
3. 只能存储字符串类型,复杂数据类型会转化为json字符串保存
4. 应用场景:适合长期保存在本地的数据
5. 操作localStorage
//设置localStorage,有则修改,无则添加
//将键值对存储在localStorage中
localStorage.setItem("key", "value");
// 获取localStorage
var value = localStorage.getItem("key");
//删除localStorage
localStorage.removeItem("key");
//清空localStorage
localStorage.clear();
sessionStorage:
1. 当前会话下有效,关闭浏览器,数据清除
2. 保存在客户端,不与服务器进行交互通信
3. 只能存储字符串类型,复杂数据类型会转化为json字符串保存
4. 应用场景:敏感账号、一次性登录
5. 操作sessionStorage
//设置localStorage,有则修改,无则添加
//将键值对存储在localStorage中
sessionStorage.setItem("key", "value");
// 获取localStorage
var value = sessionStorage.getItem("key");
//删除localStorage
sessionStorage.removeItem("key");
//清空localStorage
sessionStorage.clear();
3.cookie
基于HTTP协议的存储方式,浏览器普遍支持,容量4k
限制性:需要设置过期时间,过期自动清除,如果不设置,浏览器关闭就清除
优点:
1. 可以控制过期时间,有一定的安全保障
2. 可进行扩展,可跨域共享
3. 通过加密与安全传输技术(SSL),可降低cookie被破解的风险
4. 有较高的兼容性
缺点:
1. 有数量和长度限制,每个cookie长度不能超过4kb,超过部分会被截掉
2. 请求头上的数据容易被拦截攻击
//操作cookie
//获取cookie:
//获取所有cookie
var cookies = document.cookie;
//返回的是一个字符串,形如"cookie1=value1; cookie2=value2"
//使用splice(;)方法将字符串截并存储在数组中,方便提取数据
//修改cookie:有则修改,无则添加
document.cookie = "name=value; expires=expiration_date; path=path; domain=domain; secure";
//name是Cookie的名称,value是Cookie的值。
//expires是失效日期,格式为"Mon, 28 Jun 2023 13:24:25 GMT"。
//path是可访问该Cookie的路径,默认是当前文件路径。
//domain是可访问Cookie的域名,默认是当前域名。
//secure指定Cookie只在使用HTTPS连接的情况下才发送。
// 删除cookie:
document.cookie="要删除的键名=随便; expires=一个过去时间的GMT格式"
sessionStorage、localStorage与cookie的区别
1. 存储空间更大
2. 节省网络流量
3. 安全性更高,不用担心被截取
4. 三者都是只能储存字符串,如果用WebStorage(sessionStorage、localStorage)存储对象,会出现 [Object Object], 可以用 JSON.stringify 与 JSON.parse方法来解决这个问题。
5. sessionStorage、localStorage以(key,value)的形式存储数据,cookie以键1=值1的形式存储数据
6. sessionStorage、localStorage是作为window对象的属性存在,可以直接通过window.sessionstorage、window.sessionstorage来访问
4. IndexDB
5. Web SQL
缓存类
1. Cache Storage
2. Application Cache
11.vite和webpack的区别
- Vite和Webpack都是现代化的前端构建工具,用于打包、编译、压缩和优化前端代码。
- 主要目的是将多个源文件(例如JavaScript,CSS和HTML文件)打包成更少的文件,以便在浏览器中加载更快,同时提供许多其他功能。
- 相同点
1. 都可以处理各种静态资源,例如HTML、CSS、JavaScript、图片和字体等
2. 都支持模块化开发,可以使用ES Modules、CommonJS、AMD等模块规范
3. 都支持开发模式和生产模式,可以对代码进行压缩、混淆和优化等处理
4. 都支持插件机制,可以扩展和定制构建流程
5. 都可以处理热模块替换(HMR),在开发过程中快速更新修改的代码
- 不同点
1. 构建方式不同
Webpack采用静态依赖关系,需要在配置文件中声明入口文件和输出文件,并通过loader和plugin进行配置。Webpack的构建方式比较复杂
Vite采用动态导入方式,通过本地服务器实现快速构建和启动。Vite的构建方式比较简单,无需配置多个入口文件和输出文件,同时可以自动识别模块依赖关系
2. 速度不同
Webpack在处理大型项目时,构建速度可能会变慢。这是因为Webpack在进行打包时,需要处理所有的模块,包括未使用的模块。这使得Webpack的构建速度变慢
Vite采用了按需编译方式,只会编译当前页面的相关模块,而不会处理未使用的模块。这使得Vite的构建速度更快,可以快速启动项目和进行热更新
3. 适用范围不同
Webpack适用于大型复杂的Web应用程序,可以处理各种类型的静态资源,并提供了强大的插件机制,可以满足各种复杂的构建需求
Vite适用于中小型Web应用程序,以及需要快速启动和热更新的开发场景。Vite提供了快速构建和启动的能力,可以让开发者更加专注于业务逻辑的开发
- 总结
1.如果需要构建大型项目或对模块化支持有较高要求,那么Webpack是比较好的选择
2.而如果是在开发模式下需要快速迭代,并且对性能有要求,那么Vite则是一个很好的选择
12.状态管理存储 , localstorage
@不熟 13.H5新特新:Web Worker、WebSocket
- Web Worker
- WebSocket
14.Vue 生命周期的理解
vue2
1. beforeCreate()
实例完全被创建之前,会执行这个函数
beforeCreate()执行时,data和methods中的数据还没有被初始化
2. created()
在created中,data和methods都已经被初始化好了
如果要调用methods中的方法,或者操作data中的数据,最早只能在created中操作
3. beforeMount()
模板已经在内存中编译完成,但是尚未把模板渲染到页面中
4. mounted()
内存中的模板已经真实的挂载到页面中,用户已经可以看到渲染好的页面
5. beforeUpdate()
当执行beforeUpdate的时候,页面中的显示的数据还是旧的,但data数据是最新的,页面尚未和最新的数据保持同步
6. updated()
updated事件执行的时候,页面和data数据已经保持同步了,都是最新的
7. beforeDestroy()
实例销毁前调用vm.$destroy()时触发,实例被销毁的前夕
8. destroyed()
实例销毁完毕,该钩子被调用后,对应Vue实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。(以后页面就无法动态更新数据了。也就是说无法数据驱动视图。)
- vue2常用的生命钩子
1. mounted(执行一些初始化操作):发送ajax请求、启动定时器、绑定自定义事件、订阅消息
2. beforeDestroy(执行一些收尾工作):清除定时器、解绑自定义事件、取消订阅消息
- 关于销毁vue实例
1. 销毁后借助Vue开发者工具看不到任何信息。
2. 销毁后自定义事件会失效,但原生DOM事件依然有效。
3. 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
vue3选项式
- vue3选项API,生命周期钩子是被暴露Vue实例上的选项,只需要调用这个方法并为这个生命周期钩子编写代码。
- vue3选项式API生命周期与vue2大致相同,beforeDestroy()、destroyed()改为beforeUnmount()、unmounted(),实际上作用和用法是一样的
vue3组合式
1. steup 创建实例前
2. onBeforeMount 挂载DOM前
3. onMounted 挂载DOM后
4. onBeforeUpdate 更新组件前
5. onUpdate 更新组件后
6. onBeforeUnmount 卸载销毁前
7. onUnmounted 卸载销毁后
- 总结
1. 与vue2、vue选项式想比,去掉了两个生命周期API(beforeCreate、created),添加了setup
2. 方法名发生变化,名称前多了on,中间使用驼峰式命名
3. 卸载组件的生命周期变化:onBeforeUnmount 、onUnmounted
4. 同一个生命周期可以触发多次
15.谈一谈对 MVVM 的理解?
- MVVM是 Model-View-ViewModel 的缩写
Model:数据模型
View:ui组件
ViewModel:一个同步View 和 Model的对象,连接Model和View
- 在MVVM架构下,viewmodel通过双向数据绑定把model与view连接起来,model与view没有直接联系,
- model与view之间的交是相互的,因此view数据的变化会同步到model中,model数据的变化也会立即反应到view上
- model和view之间的同步工作是完全自动的,无需人为操作
16.Vue 实现双向数据绑定的原理?
vue2
- 在组件创建时,vue会对对组件的data中的每个属性进行代理
- 当组件中任何一个属性发生变化时,vue会通过Object.defineProperty()方法重新定义该属性的setter方法,从而在属性被重新赋值时触发对应的wather更新对应的DOM节点
vue3
- Vue3的双向数据绑定底层使用了Proxy API来进行代理。
- 在组件创建时,Vue3会对组件的data中的每个属性进行代理,使用了Proxy中的handler中的set方法,当组件中的任何一个属性发生变化时,就会触发set方法,从而更新对应的DOM节点。
17.Vue2.x 中如何检测数组的变化?
- 通过vue重写后的7个数组方法(push,pop,shift,unshift,sort,splice,reverse)检测数组的变化
- vue将data中的数组,进行了原型链重写。通过原型链指向了重新定义后的数组方法,当调用数组api时,可以通知依赖更新。如果数组中包含引用类型,会对数组内的引用类型再次监控
不熟@ 18.vue2.x 和 vuex3.x 渲染器的 diff 算法分别说一下?
vue2
vue3
19.Vue 的路由实现
- 路由的原理: 通过改变URL,在不重新请求页面的情况下,更新页面视图
- 有两种:HashHistory路由、history路由
HashHistory路由
- vue默认使用hash路由
- hash(‘#’)的作用是加载url中指示的网页的位置
- HashHistory路由的特点
1. 路由地址会有#
2. `#`后面的内容不会传给服务器,也就是说不会重新刷新页面,路由切换也不会重新加载页面
3. 每次改变hash(window.localtion.hash),都会在浏览器增加一个历史记录
举例:
http://localhost:8080/#/a
//变为 如下地址,浏览器访问历史中会增加一个记录
http://localhost:8080/#/b
4. 可以为hash的改变添加监听事件`window.addEventListener("hashchange",funcRef,false)`
- HashHistory路由的两个方法
1. hashHistory.push() 将路由添加到浏览器访问历史的栈顶,之前的路由还存在,可以返回之前路由
2. hashHistory.replice() 将路由替换掉当前路由,当前路由会成为最新路由,之前的路由会被覆盖,无法返回之前路由
history路由
HIstory interface
是浏览器历史记录栈提供的接口,通过back()、forward()、go()等方法,可以读取浏览器历史记录栈的信息,进行各种跳转操作- history路由原理
利用History interface在H5中新增方法pushState()、replaceState(),对浏览器历史记录栈进行修改
- 特点
1. history路由模式,实现单页面的url中没有#,当用户改变路由时,会向服务器发送请求
2. 为了避免这种情况,所以history路由实现方式需要服务器的支持,需要把所有的路由都定向到根页面
3. 在HTML5 History 的构造函数中监听使用popState(window.onpopstate)
- history路由的两个方法
// stateObject:当浏览器跳转到新的状态时,将触发Popstate事件,该事件将携带这个stateObject参数的副本
// title:所添加记录的标题
// url:所添加记录的url
// 和hashHistory.push()功能相似,将路由添加到浏览器访问历史的栈顶,之前的路由还存在,可以返回之前路由
window.history.pushState(stateObject,title,url)
//和hashHistory.replace()功能相似,将路由替换掉当前路由,当前路由会成为最新路由,之前的路由会被覆盖,无法返回之前路由
window.history,replaceState(stateObject,title,url)
两种路由模式的区别
- history模式设置的新的URL可以是与当前URL同源的任意URL
hash模式只可修改#后边的部分,故只可设置与当前文档同文档的URL - history模式通过stateObject可以添加任意类型的数据到记录中
hash模式只可添加短字符串 - history模式可额外设置title属性后供后续使用
hash模式没有该功能 - history模式会将URL修改得就和正常请求后端的URL一样,如后端没有配置对应的路由处理,则会返回404错误
hash模式只改变#后面的内容,跳转路由不刷新页面,故不会向后端发送请求
两种路由模式跳转API的区别
API | hash模式 | history模式 |
---|---|---|
push | hashHistory.push() | window.history.pushState() |
replice | hashHistory.replice() | window.history,replaceState() |
go | window.history.go | window.history.go |
back | window.history.go(-1) | window.history.go(-1) |
forward | window.history.go(1) | window.history.go(1) |
20.vuex和pina的区别?
vuex
- 核心属性:
1. state:单一状态树,用来存储所有的共享数据
//调用方法:
this.$store.state.全局数据名称
2. getters:状态获取,相当于`state`的计算属性,具有返回值的方法
//调用方法:
this.$store.getters.方法名
3. mutation:触发同步事件,用于修改state中存储的数据
//建议通过mutation操作state中的数据,虽然操作复杂,但可以集中监控state里所有数据的变化
//直接操作state,state里的数据是无法监控的
//Mutation中不可以执行异步操作,如需异步,在Action中处理
//调用方法:
this.$store.commit('方法名',值)
4. actions:触发异步事件,用于处理异步任务的,比如网络请求等
//调用方法:
this.$store.dispatch('方法名',值)
5. module:将vuex进行模块拆分
//模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理
- 总结
- 修改state状态必须通过mutations
- mutations只能执行同步代码,类似ajax、定时器之类的代码不能在mutations中执行
- 执行异步代码,要通过actions,然后将数据提交给mutations才可以完成
- state的状态即共享数据可以在组件中引用
- 组件中可以调用action
pinia
- 核心属性
1. state:用来储存全局的数据
//访问state:
const store=useStore()
store.变量名
//重置state:
const store=useStore()
store.$reset()
2. getter:监视计算状态的变化,有缓存功能
//Getter 等同于 store 的 state 的计算值
//调用方法
const store = useStore()
store.方法名
3. action:修改state内的全局状态数据
//调用方法
const store = useStore()
store.方法名
vuex与pinia的区别
- Vuex和Pinia都是Vue.js的状态管理库
- 区别
- vuex是vue.js官方提供的状态管理库
<br>
pinia是基于vue3且使用TS编写的轻量级状态管理库- vuex提供了更完整、更复杂的接口和功能集,如模块、插件等
<br>
pinia只提供了片段式组装store等核心需求- vuex相对稳定,文档和社区支持完善
<br>
pinia侧重于TS风格的开发方式,未来可能会提供更好的维护性和易读性
21.nextTick
的作用是什么?他的实现原理是什么?
- vue中DOM更新是异步的
- vue实现响应式不是数据发生变化后,DOM立即变化,而是按一定的策略进行DOM更新的
- 作用
用于下次DOM更新循环结束后执行回调,在修改数据之后使用
nextTick
,则可以在回调中获取更新后的DOM
- 应用场景
- 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
<br>
原因:在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的 js 代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
<br>
- 需要在视图更新后,基于新的视图进行操作
- 实现原理
nextTick
主要是使用了宏任务、微任务,定义了一个异步方法,多次调用nextTick
会将方法存入队列中,通过这个异步方法情况队列
22.热更新
- 当代码发生变化时,页面会根据更新后的代码发生变化,无需重新加载页面
23.服务端渲染(SSR)
1. SSR(server side render)服务端渲染
2. CSR(client side render)客户端渲染
3. SPA(single page application)单页面应用
4. SEO(search engine optimization)搜索引擎优化
5. SSG(static side generate)预渲染
6. AJAX(Asynchronous Javascript And XML)在不重新加载整个网页的情况下,对网页的局部数据进行更新
什么是服务端渲染
服务器端完成页面的DOM结果拼接,然后发送到浏览器,为其绑定状态和事件,成为完全可交互的过程
优点
- 前端耗时少,因为后端拼接完html,前端只需直接渲染出来
- 有利于SEO,因为在后端有完整的html页面,有利于爬虫爬取信息,更利于SEO
- 降低占用客户端资源,因为解析模板的工作完全交给后端,客户端只需解析标准的html页面即可,对客户端的资源占用更少,尤其是移动端,更省电
- 后端生成静态化文件,可以降低数据查询浪费的时间,对于数据变化不大的页面非常高效
缺点
- 不利于前后端分离,开发效率低
- 占用服务器端资源
服务器端渲染的方式
- JSP(JavaServer Pages)
- express + ejs
- express + react
- vue + nuxt
应用场景
- 适用于客户端渲染的项目
- 企业内部项目,管理平台这类不需要SEO的项目,使用客户端渲染能能够提高开发效率,减少服务器资源占用;
- 强交互项目:对于交互比较多,数据不是很固定的项目,使用客户端渲染,能够让用户更临近于原生APP体验;
- 适用于服务端渲染的项目
- 官网、博客网站、营销类网站:这些网站对SEO和首屏渲染速度更加注重,所以服务端渲染会是较好的选择;
24.react-hooks
- 什么是hooks
hooks意思是钩子,react hooks就是一堆钩子函数
- 作用
对函数型进行增强,让函数组件可以存储状态,可以用有处理副作用的能力,让开发可以在不使用类组件的i情况下,实现相同功能
- 副作用
- 代码中只要不是把数据转换成视图的代码他就属于副作用
- 副作用代码:发送ajax请求,获取dom,添加点击事件
- 在类型组件中,一般使用生命周期函数去处理副作用,而在这些函数型组件中,我们就要使用hooks去处理这些函数
- 常见的react hooks
1. useState()
- 作用:用于函数组件引入状态
- useState()方法内部是使用闭包保存状态数据的
- 使用细节
1. 接收唯一的参数即状态初始值。初始值可以是任意数据类型 2. 返回值为数组。数组中存储状态值和更改状态值的方法。方法名称约定以set开头。后面加上状态名称 3. 方法可以被多次调用,用以保存不同的状态值 4. 参数可以是一个函数,函数返回什么,初始值就是什么,函数只会被调用一次,用在初始值是动态值的情况
2. useReducer()
- 作用:让函数组件保存状态
- 使用方式和rudux的reducer相似,状态都被保存在一个特殊的地方
- 使用细节
第一个参数就是reducer函数,我们创建reducer函数去进行对数据的处理, 第二个参数为状态的初始值 函数的返回值返回一个数组,数组里面有两个值一个是存储的状态,第二个是触发action的dispatch方法 自己创建的reducer函数接受两个值,一个是存储的状态另外一个就是触发的action
3. useContext()
- 作用:在跨组件层级获取数据时简化代码
4. useEffect()
- 作用:让函数型组件拥有处理副作用的能力。类似生命周期函数
5. useMemo()
- 作用:类似Vue中的计算属性,可以检测某个值得变化,根据变化值计算新值
- useMemo会缓存计算结果。如果检测值没有发生变化,即使组件重新渲染,也不会重新计算
- 有助于避免在每个渲染上进行昂贵的计算
6. useCallBack()
- 作用:性能优化,缓存函数,使组件重新渲染时得到相同的函数实例
- 使用场景:
当子组件通知父组件的时候,子组件内部状态没有发生改变但是还是进行了重新渲染,memo虽然解决 子组件内部状态没有变阻止子组件重新渲染问题,但是当父组件状态改变,组件发生了重新渲染, 新渲染过后每一次生成的改变状态的函数的实例都变了,导致传递给子组件的方法中的实例变了, 传入的函数实例改变,子组件就会认为组件内部的状态发生了改变,他就会导致重新渲染。解决这 问题的方法就是让传给子组件的函数实例都是同一个这里就要用到useCallBack()
7. useRef()
- 作用:获取dom元素对象,保存数据(跨组件周期)
8. 自定义hooks
- 自定义hook是标准的封装和共享逻辑的方式
- 自定义hook是一个函数,其名称以use开头
- 自定义hook其实就是逻辑和内置Hook的组合
9. React路由Hooks
- 包含了四个钩子函数
useHistory()
useLocation()
useRouteMatch()
useParams()
- 作用:获取相关的路由信息
25.redux
- 相当于vue中的vuex
- redux 是一个独立专门用于做状态管理的 JS 库(不是 react 插件库)
- 它可以用在 react, angular, vue 等项目中, 但基本与 react 配合使用
- 作用: 集中式管理 react 应用中多个组件共享的状态
- 核心概念
- Store
1. 在 redux 里面,只有一个Store,整个应用需要管理的数据都在这个Store里面。 2. 不能直接改变Store的数据,只能通过返回一个新的Store去更改它。 3. redux提供了一个createStore()方法来创建state
- action
视图层发起的一个操作,通过action改变store内的数据
- Reducer
作用:调用action里的方法 在redux里面,store.dispatch()是 View发出 Action 的唯一方法
26.call、apply、bind的作用和区别
共同点
- 都可以改变函数内部的this指向
不同点
- call和apply会调用函数,并且改变函数内部this指向。
- call和apply传递的参数不一样,call传递参数arg1,arg2…形式apply必须数组形式[arg]
- bind不回调用函数,可以改变函数内部this指向。
call()方法
- 改变函数内部this指向,同时调用该函数
- 语法:
fun.call(thisArg,arg1,arg2,...)
//thisArg为想要指向的对象,arg1,arg2为参数
- 应用场景:实现继承
apply()方法
- 改变函数内部this指向,同时调用该函数
- 语法
un.apply(thisArg,[argsArray])
//thisArg:在fun函数允许时指定的this值
//argsArray:传递的值,参数必须放在数组里面
//返回值就是函数的返回值
- 应用场景:求数组中最大值
bind()方法
- 改变函数内部this指向,不会调用该函数
- 语法
fun.bind(thisArg,arg1,arg2,...)
//thisArg:在fun函数运行时指定的this值
//arg1,arg2:传递的其他参数
//返回由指定的this值和初始化参数改造的原函数拷贝
- 应用场景:有的函数我们不需要立即调用,但是又需要改变这个函数的this指向,此时用bind再合适不过了
27.this指向
概念
在js中,this是一个指针型变量,它动态指向当前函数的运行环境
在不同的场景中调用同一个函数,this的指向也可能会发生变化,
永远指向其所在函数的真实调用者;如果没有调用者,就指向全局对象window
this的指向
- 普通函数:
- 严格模式下,必须要写调用该函数的对象,有则this指向该对象,无则undefined
- 非严格模式下,this指向调用该函数的对象
//在严格模式下,对代码的的调用必须严格的写出被调用的函数的对象,不可以有省略或者说简写。
function fn(){
"use strict" //使用严格模式
console.log(this);
}
fn(); //输出undefined
window.fn(); //输出window
//非严格模式下,通过test()和window.test()调用函数对象,this都指向window。
function fn(){
console.log(this);
}
fn(); //输出window
window.fn(); //输出window
- 箭头函数:箭头函数的this指向于函数作用域所用的对象
1. 创建箭头函数时,就已经确定了它的 this 指向。
2. 箭头函数内的 this 指向外层的 this。所以要知道箭头函数的 this 就得先知道外层 this 的指向
- 在全局作用域下,this始终指向全局对象window,无论是否是严格模式
//全局作用域下的this指向
//console.log()完整的写法是window.console.log(),window可以省略
//window调用了console.log()方法,所以此时this指向window
console.log(this) //输出window
- 对象中的函数:
- 普通函数:this指向对象
- 箭头函数:this指向window
let obj={
a:()=>console.log(this),
fn(){console.log(this)}
}
obj.a() //输出window
obj.fn() //输出{a: ƒ, fn: ƒ}
- 构造函数
1. 当使用 new 关键字调用构造函数时,函数中的 this 指向实例新对象
2. 直接调用,this指向调用者
- 事件绑定中的this
1. 行内绑定,this指向window
2. 动态绑定与事件监听,this指向节点对象
- 改变this指向的方法:call()、apply()、bind()
//call()方法,改变this同时调用函数
函数名称.call(obj,arg1,arg2…argN);
//apply()方法,参数二是一个数组,改变this同时调用函数
函数名称.apply(obj,[arg1,arg2…,argN]);
//bind()方法,和call类似,改变this,但不会调用函数
函数名称..bind(obj);
28.垃圾回收机制
- 什么是垃圾
- 没有引用的对象或变量
- 无法访问到的对象(多个对象相互引用成环)
- 垃圾回收机制
间歇的不定期的寻找那些不再使用的对象或变量,并释放掉他们占用的内存
目的:防止内存泄漏,减小浏览器内存压力
- 检测垃圾的方式:标记清除法、引用计数法
标记清除法
当函数执行开始,给函数内的变量打上“进入环境”的标记,当函数执行结束后,不再被引用的变量标记为“离开环境”,将这些标记为“离开环境”的变量删除
29.EventLoop(事件循环)
- 同步任务 > nextTick > 其他微任务 > 宏任务
- 宏任务:I/O、定时器、事件绑定、ajax
- 微任务:Promise的then、catch、finally和process的nextTick
- Promise的then等方法是微任务,而Promise中的代码是同步任务
30.内存溢出和内存泄漏
内存泄露
- 用动态储存分配函数内存空间,在使用完毕后未释放,导致一直占据该内存单元,直到程序结束。
- 常见的内存泄漏:闭包、计时器、回调、事件监听
- 无用的变量占据了有用的内存
内存溢出
- 不顾堆栈分配的局部数据块大小,向数据块中写入过多数据,导致数据越界,结果覆盖了别的数据。常在递归中发生。
- 内存溢出一般是内存泄漏造成的,会造成浏览器内存不足,崩溃掉