目录
- react、vue、angular、jq:生命周期,特点,优缺点,版本区别
- Mvc、mvvm、flux、redux、vuex定义与特性
- 列表key属性、jsx原理
- React如何减少组件无重用渲染
- React Hooks相关问题
- Sass(scss)、less、css: 区别,特点
- Es6、es7、es8、H5、css3:特性,map, set,
- flex布局、垂直居中、清除浮动、BFC、三栏布局、两栏布局、动画、盒模型、等宽等高
- 移动端适配
- 跨域、解决方法
- Promise
- http1、http2、https、状态码:版本区别
- 浏览器的缓存
- Url输入后发生什么
- Ajax、axios、fetch:区别、特点、原理、优缺点、流程
- React-router、router、hash、history的原理使用
- 兼容性问题: 浏览器、前端
- 线程、进程
- 节流、防抖
- 代理、变量、作用域、垃圾回收、内存泄漏、call/applay
- 事件委托、事件监听、事件处理函数、
- 继承、闭包、原型、原型链、面向对象、循环、
- 声明组件的方式
- 有无状态组件、受控非受控组件:
- 判断一个类是否继承另一个类的方法
- Webpack、gulp:区别、特点
- 前端优化、react优化、vue优化、性能优化、webpack优化
- 算法、排序
- 高阶函数
- Amd/cmd
- 单页面应用、优缺点、实现方式
- Git、
- 网络安全、xss攻击
- 小程序
- Node
- Js、d3、svg、echarts、highcharts、ant-g6、mxgraph
react、vue、angular、jq:生命周期,特点,优缺点,版本区别
| 主题 | react | vue | angular | jq | |
| 体系结构 | 只有mvc中的view mvc | mvvm | 完成的mvc | ||
| 渲染 | 可以进行服务端渲染 | 客户端渲染 | |||
| dom | 使用虚拟dom | 使用虚拟dom | 使用真实dom | ||
| 数据绑定 | 单向数据流 | 双向数据绑定 | 双向数据绑定 | ||
| 调试 | 编译时调试 | 运行时调试 | |||
| 作者 | 尤雨溪 | ||||
| 定义 | facebook在2011年开发的js库,2015年开源,遵循基于组件的方法,有助于构建可重用的组件 | ||||
| 特点 | 使用虚拟dom,可以进行服务端渲染,单向数据流 | Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。 | |||
| 优点 | 方便在客户端和服务端使用,因jsx,代码可读性高,由于虚拟dom,提高性能 | 简单易学、双向数据绑定、运行速度快虚拟dom,单页面应用 | |||
| 缺点 | 只是一个庞大的库,不是一个完整框架,需要时间来理解 | vue不支持IE8 | |||
| 生命周期 | - componentWillMount渲染前,客户端服务端都执行 |
- componentDidMount第一次渲染后在客户端执行
- componentWillReceiveProps当从父类接受到props
- shouldComponentUpdate根据条件返回true/false
- componentWillUpdate在DOM中进行渲染之前调用
- componentDidUpdate渲染发生后立即调用
- componentWillUnmount从DOM卸载组件后调用,清理内存空间 | - beforeCreate(创建前) 在数据观测和初始化事件还未开始
- created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
- beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
- mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
- beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
- updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
- beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
- destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
Mvc、mvvm、flux、redux、vuex定义与特性
| mvc | mvvm | flux | redux | react-redux | vuex | |
| 模式 | model 数据层view 视图层control 逻辑层当用户对view层有改变时,它负责修改响应的model,model发生变化,负责去更新视图层 | model:数据层view: 视图层vm:view和model通过vm层自动同步 | 强制的单向数据流的架构模式, | 洋葱圈模式:用户通过点击等等一些事件,触发一个action,通过store.dispatch分发这个action,通过Reducer这个存函数去改变store中的状态,通过监听事件subscribe监听store的变化,然后才会视图层更新 | import引入storegetState获取状态dispatch修改状态subscribe监听跟新 | |
| 组件 | - action:描述发生事情的对象 |
- reducer:纯函数,确定状态如何改变,返回新的状态
- store:整个状态存储的地方
- view:只显示store提供的数据 | Provider:将store放进this.context 里,为connect提供获取store的途径;Connect:将getState、dispatch合并进this.props,自动监测更新,接受mapStateToProps、mapDispatchToProps两个方法,返回一个高阶函数,高阶函数接受一个组件,返回一个高阶组件(其实就是给传入的组件增加一些属性和功能),connect根据传入的,将state和dispatch(action)挂在子组件的props上, | | | 原则 | | | | - 单一来源store存储所有状态
- 状态只读,改变状态需要触发动作,动作是描述变化的js对象
- 使用纯函数进行更改
- 数据流:
- 中间件:增强对dispatch功能 redux-logger:提供日志输出 redux-thunk: 处理异步操作,对actionCreator进行操作 redux-promise:处理异步操作 redux-saga: 把异步请求放在了saga文件中 | | | | 优点 | | | | 结果可预测性:只有一个store的状态来源可维护性更高服务端渲染 | | | | 缺点 | - 对DOM操作的代价非常高
- 程序运行缓慢,效率低下
- 内存浪费严重
- 由于循环依赖性,组件模型需要围绕models和iviews进行创建 | | | 一个组件所需要的数据,必须由父组件传递过来,不能直接从store中取 | | |
列表key属性、jsx原理
key:识别唯一的虚拟dom元素及其驱动ui的标识,必须是唯一的数字或字符串,他们通过回收DOM中当前所有的元素来帮助react优化渲染,react只是重排元素,而不是重新渲染,提高性能
jsx: react使用的一种文件,利用js和类似html的模板语法,让html文件更容易理解,提高性能;
浏览器只能处理js对象,不能读取js中的jsx,需要用babel JSX转换器将jsx转为js对象,传给浏览器
React如何减少组件无重用渲染
| 问题 | 答案 | 解决 |
| state的值未变化,是否会重渲染 | 会 | shouldComponentUpdate(nextProps, nextState)nextState.num ===this.state.num return false, 只能是偏平的对象,如果nextState.numObj.num === this.state.numObj.num 二者都指向堆中同一个对象,所以一直都是true,shoucomponentUpdate就失效了如果获取到不同的numObj?1、ES6的object assign();2、利用JSON.parse(JSON.strigify(data))深拷贝 |
| 组件state和父组件传的props都没变,是否会重渲染 | 可能 |
React Hooks相关问题
hooks优势:
在无需修改组件结构的情况下复用状态
将组件中想关联的部分成更小的函数
函数组件的渲染过程:每一次渲染,就是函数的重新执行
useState和setState的区别:
useState 只能在函数组件;在函数组件中可以声明多个;修改state时,同一个useState声明的值被覆盖,多个useState声明的值被触发多次渲染;设置相同值,不会重渲染;
setState 只能在类组件; 在类组件中必须声明在this的state对象中;修改sate时,多次setState的对象呗合并处理;设置相同值会被重渲染;
useState和useReducer的初始值如果是个执行函数返回值,执行函数是否会多次执行:
前者不会,后者会
useState设置初始值时,如果初始值是个值,可以直接设置,如果是个函数返回值,建议使用回调函数设置(只会在初始化时执行一次);
useReducer设置初始值时,只能是个值,不能是回调函数,因为组件重新渲染时,会重新执行函数
useEffect如何模拟componentDidMount、componentUpdate、componentWillUnMount生命周期
componentDidMount: useEffect(() => {}, [])
componentUpdate: useEffect(() => { if (count !== 0) { } }, [count]) 使用条件判断依赖项是否为初始值
componentWilllunMount: useEffect(() => { return () => {} }, []) 返回函数被执行,组件被卸载, 依赖项必须为空数组,如果不是,是在组件重新渲染,清理上一次数据时触发
如何在useEffect中正确的为DOM设置事件监听
在useEffect中设置监听,在return的函数中清理,取消监听事件
useEffect、useCallback、useMemo中取到的state、props为什么会是旧值
三者都具有缓存功能,如果依赖项为空数组,那么改变多少次,变量都是初始值
useEffect为何会无限执行
如果没有设置依赖项,并且在useEffect中更新state,会导致无限重复渲染 useEffect(() => { setCount(count + 1) })
如何解决无限重渲染: 设置空数组依赖项,相当于给页面初始值设置了一个新值
依赖项设置[count, page],count+1, page+1, 也导致的页面重复渲染:useEffect(() => { setPage(page => page + 1) }, [count])
竞态:多次刷新页面,有时展示0,有时展示10
设置布尔值变量进行追踪, useEffect(() => {
let didCancel = false;
const getData = async () => { const result = await fetchData(id) if (didCancel) { setData(result) }}
getData()
return () => { didCancel = true }
, [id])
如何在函数组件中保存住非state/props的值,函数组件实例的属性
重新渲染时,countRef不会被重新赋值,但modal构造函数会多次执行
如何保证在函数组件的每一帧里访问到的state值是相同的
函数组件是没有this指向的,为了保存组件实例的属性,用useRef操作,将普通类型的值转为一个带有current属性的对象引用,来保证每次访问到的属性值是最新的
如何在函数组件中保存一些属性,跟随组件进行创建和销毁
当useCallback会频繁触发时,如何优化
使用useReducer替代useState,useReducer返回的dispatch函数自带memoize,不会再多次渲染时改变,因此useCallback中不需要将dispatch作为依赖项
向setState中传递函数,在setCount中使用函数作为参数时,接受到的值是最新的state值
useCallback和useMemo的使用场景有何区别
useMemo返回时一个值,可以是属性,可以是函数(包括组件),用来缓存计算量比较大的函数结果,避免不必要的重复计算
useCallback的返回值只能是函数
useMemo和React.memo不同
useMemo是对组件内部的一些数据进行优化和缓存
React.memo是对函数组件进行包裹,对组件内部的state、props进行浅比较,判断是否需要进行渲染
useContext使用
定义静态属性的方式
function component
Sass(scss)、less、css: 区别,特点
less是基于js的,在客户端处理,2009年开源;变量用@
sass是基于ruby的,在服务端处理,2007年开源;变量用$
scss语法用{}取代了sass中的缩进
sass与less相同处:1、运算,css用上数学;3、作用域,全局/局部修改样式;4、嵌套
多行注释会被编译出来,单行不会
Es6、es7、es8、H5、css3:特性,map, set,
| ES6(2015) | ES7(2016) | ES8(2017) | ES9(2018) | ES10(2019) | H5 | Css3 |
| 类:子类必须在construcor中指定super函数,否则会报错如果没有指定construtor,默认带super函数的constructor将会被添加 | Array.includes() => true/false | async/await | 异步迭代 | array的flat(reduce归纳,降维)与flatMap(concat合并)的操作[1,2,[3,4]].flat() => [1,2,3,4] 降一维,去除数组空项[1,2,[3,4,[5,6]]].flat(Infinity) 任意深度的展开嵌套数组[1,2,3,4].map(x => [x2]) => [[2], [4],[6],[]][1,2,3,4].flatMap(x => [x2]) => [2,4,6,8]只压平一层 | 语义化标签HeaderNavSectinArticlefooter | 圆角 border-radius多背景 background过滤旋转 scale缩放 移动 tansform倾斜 |
| 模块化:主要由export和import组成;import引入其他模块,export规定对外暴露的名字,都有自己单独的作用域 | Object.values() | Promise.finally()无论promise成功失败都运行代码 | string的strimStart()和strimEnd去除收尾空白符 | 表单元素passwordemailurladdressdate | ||
| 箭头函数:解决this指向, | Object.entries() 返回键值对的数组 | rest/spread属性 | 多媒体audiovedio | |||
| 模板字符串 | string paddingpadStart()padEnd() | 缓存浏览器缓存:localstorage, sessionStorage | ||||
| 数组的解构赋值 | 新的通信方式: websoket | |||||
| 延展操作符:...[]/{} | 3d图像: canvas svg webgl | |||||
| promise对象 | ||||||
| let/const 块级作用域,没有变量声明提升,否则会报错,不能重复定义,报错let定义,可以改,const定义,如果是引用类型,可以修改对象里的属性值(因为对象指针没变),否则会报错 |
Js基本数据类型
基本类型:number、string、boolean、undefined、null 值存在栈中
引用类型:object、array、function 引用存在栈中,真实的数据在堆中,不同的引用可以指向堆中的同一个对象
判断引用类型方法:Object.prototype.toString.call(target) === 'Array' / 'Object'
深拷贝:重新创造一个新对象,新旧对象互不影响
深拷贝方法:
JSON.parse(JSON.stringify()) 但不能深拷贝函数,fn 深拷贝是个null,因为JSON.stringify()是将一个js对象或数组转成json字符串,不能接受函数;
_.clonDeep
浅拷贝:赋值的是对象的引用,同一个对象,影响;
浅拷贝方法:
Object.assign()对象有一层,是深拷贝,否则是浅拷贝;
Array.concat() ;
Array.slice();
flex布局、垂直居中、清除浮动、BFC、三栏布局、两栏布局、动画、盒模型、等宽等高
BFC:块级格式化上下文,一个独立的渲染区域,内部如何布局,不会影响外部
特点:内部元素会在垂直方向上一个接一个放;
垂直方向上的距离由margin决定;
bfc区域不会与float的元素区域重叠;
形成BFC:浮动元素,float除none以外的值;
绝对定位的元素,position: absolute,fixed;
display: inline-block,table-cell,flex;
overflow除visible以外的值:hidden,auto,scroll;
body根元素;
盒模型:
标准盒模型(W3C盒模型): content + padding + border + margin width和height不包含padding和border
box-sizing: content-box(浏览器默认设置) j将采用标准盒模型
怪异盒模型(IE盒模型):width(content + padding + border) + margin width和heigh都包含padding和border
box-sizing: border-box; 将采用怪异盒模型
box-sizing: inherit; 从父元素继承box-sizing属性的值
| 垂直居中 | 让图片垂直局居中 | 不固定宽高垂直居中 | 清除浮动 | 三栏布局(左右固定高度,中间自适应) | 两栏布局 | 给定宽度,如何设置高与宽度相等 | 图片大小不一致,如何垂直水平居中 |
| 父:display: table;子:display: table-cell; vertical-align:middle;优点:content动态改变高度,当父没有足够空间,content不会被截断缺点:IE中不好使 | 父:line-height: height; text-align: center; | 父: display: table-cell; text-align: center; vertical-align: middle; | 父:float: left;子:clear: both; height: 200px; | 左栏左浮动,右栏右浮动,设置宽度高度;中间设置margin撑开距离,且中间不设置宽度,高度自适应;html布局时,中间栏放在左右两栏的后面,否则,右栏会在中间栏的右下角显示 | 左栏浮动,右边margin-left撑开 | width: 33%;padding: 14% 0;padding上下设置,左右为0上下加中间文字=width | 图片父容器: width: xx; height: xx; float: left; text-align: center;图片: vertical-align: middle;与图片同级添加空: display: inline-block; width: 0; height: 100%; overflow: hidden; vertical-align: middle; |
| 父:position: relative;子:position: absolute; top: 50%; margin-top: -1/2height; left: 50%; margin-left: -1/2width;优点:使用所有浏览器;缺点:没有足够空间,content会消失 | 同左 | 父: display: flex;子: margin: auto; | 父:overflow: auto;优点: 浏览器支持好;缺点: 内部宽高超过父时,出现滚动条父:overflow: hidden;缺点:不能喝position配合使用 | 左栏定位再左侧,右栏定位再右侧,中间栏不舍宽度,靠margin撑开 | 父:display: flex左栏宽度固定,右栏flex:1 | ||
| 父:position: relative;子:position: absolute; left: 0; top: 0; bottom: 0; right: 0; height: xx; width: xx; margin: auto;优点:简单缺点:IE中无效; 没有足够空间,content被截断 | 同左 | 同左 | 父定义伪类div:after { content: ""; clear: both;}.clearfix { zoom: 1; 兼容IE} | 三栏左浮动,左栏margin-left: -100%; 右栏margin-left: 负右栏高度;中间栏宽度100%,布局中间栏放在第一个 | 父:position:relative左边:position: absolute; left: 0; top: 0;右边:margin-left撑开距离 | ||
| 父:display: flex; aligin-items: center; 垂直居中 justify-content: center; 水平居中或者父:display:flex; justify-content: center; 水平居中子:align-self: center | 同左 | 同左 | 父:height: xx;缺点:需要设置固定高度 | ||||
| 父: positino: relative;子: position:absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) | 同左 | 同左 |
移动端适配
设备像素比dpr = 物理像素 / 设备独立像素(逻辑像素)
vw 时相对屏幕的相对单位,100vw = ideal viewport 宽, 100vh = ideal viewport 高
1px边框问题及解决方案:
1px的css逻辑像素不等于1px的物理像素,所以实际显示出来的要粗
用box-shadow模拟边框来实现1px border
.boder{ border: none; height: 100px; width: 100%; box-shadow: 0 1px 1px -1px rgba(0,0,0,0.5) }
| 解决方法 | 实现 | 优点 | 缺点 |
| 媒体查询meida | 通过查询设备宽度来执行不同的css代码 @meida screen and (max-width: 600px) {} | 图片便于修改,只需要修改css跳转屏幕宽度的似乎还不用刷新页面即可响应式展示 | 代码量比较大,维护不方便为了兼顾大屏幕或高清设备,会造成其他设备资源浪费,特别是加载图片资源为了兼顾移动端和pc端各自响应式展示效果,难免会损失各自持有的交互方式 |
| flex弹性布局 | viewport固定 <meta name="viewport" content="width=device-width,initial-scale=1,maxinum-scale=1,user-scalable=no"高度定死,宽度自适应,元素采用px单位initial-scale:页面初始缩放值,可带小数;minimum-scale:设置页面的最小缩放值,可带小数maximum-scale:设置页面的最大缩放值,可带小数user-scalable:页面是否允许缩放,no不允许,yes允许;no时 ios>=10的safari有兼容性问题 | ||
| rem+viewport缩放 | 根据屏幕宽度设置rem值,需要适配的元素都使用rem做单位,不需要适配的采用px(1em=16px)rem是一个相对root的单位, | ||
| rem方式 |
跨域、解决方法
跨域:协议、域名、端口号不同
正向代理代理客户端,为客户端收发请求,隐藏客户端(翻墙,a想访问google,但它访问不了,但b可以,所以a先访问b, b再访问google,数据返回后,转发给a)
反向代理代理服务端,为服务端收发请求,隐藏服务端
好处:
反向代理保护原始服务器,比较安全,负载均衡(当很多用户访问资源服务器时,让不同的代理服务器发送不同的资源)
| 实现方式 | 优点 | 缺点 | |
| Jsonp | script标签的src="www.baidu.com/json/?callb…func", 通过script标签请求时,后端会根据响应的参数(json, func)生成相应的json数据func({ "data": "zhe" }), 这个json数据就会被放到当前的js文件中执行 | 1、只能使用get请求2、jsonp是从其他域中加载代码执行,容易受到跨站请求伪造的攻击,安全性不高3、不能注册success/error事件,无法确定请求是否成功 | |
| Cors | cross-origin resource sharing 跨域资源共享服务器添加响应头1. Access-Control-Allow-Origin: * 服务器设置第一条即可 |
- Access-Control-Allow-Methods: POST, GET, OPTIONS
- Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
- Access-Control-Max-Age: 86400默认不会携带cookie,如果要带cookie1. "Access-Control-Allow-Credentials": true
- // Ajax设置
- "withCredentials": true | | 不能修改cookie中的domain信息,不方便当前的cookie的写入,所以不饿能进行登录认证 | | WebSoket | 是一种浏览器的API,目标是在一个单独的持久连接上提供全双工,双向通信;js创建soket后,会有一个http请求发送到浏览器以发起连接,服务器响应后,建立的连接会从http协议升级到web soket协议 | | | | webpack反向代理 | 通过设置devServer的proxy的target:"xx.xx:3000", 客户端发出请求,先到代理的中间层,将本地的域名包装成目标域名,再发送给服务器,服务器返回数据,也是先到代理的中间层,把目标域名包装成本地的域名 | | | | H5新引进的window,postMessage | | | | | Document.damain | | | | | Location.hash | | | | | Window.name | | | | | Nginx反向代理 | | | |
Promise
是解决异步的,有三种状态,pending进行中, resolved已完成, rejected已失败;状态一旦改变,就无法再次改变状态
缺点:
1、回调地狱;2、嵌套导致代码可读性差;3、promise一旦执行,无法中途取消;4、如果不设置回调,promise内部的错误无法反应到外部
缺点解决方案:
1、setTImeout设置并不立刻执行;2、事件监听,表示某个事情发生才会触发;3、async/await
如何使用:
1、创建promise实例/1、再用then方法指定resolved和rejected状态的回调函数/3、用try,catch方法捕获异常
兼容老旧浏览器没有Promise对象:
使用est-promise-polyfill 可以使用页面标签直接引入,es6/import, node/require,会在window对象中引入promise对象
异步无论成功失败,都调用一个方法:
promise.finaly = func, 内部也可以return一个promise对象,继续调用其他方法
http1、http2、https、状态码:版本区别
http用的端口是80,https是443;http协议运行在tcp之上,所有传输的内容都是明文,https运行在ssl/tls(安全传输协议)之上,而ssl/tls运行在tcp之上,所有传输内容都是加密的;https需要申请证书,需要交费
http1:线程阻塞,同一时间,同一域名的请求有一定数量限制,超过限制会被阻塞;tcp连接里,按次序进行,浪费带宽
http2:多路复用,而非有序阻塞的;采用二进制格式而非文本格式;报头压缩;服务器推送,安全协议层,https
状态码:
********1开头开始请求;
2开头请求成功;200成功
3开头重定向;301网址发生改变,自动转到新位置;302临时移动;304资源未改过,服务器不会返回任何内容;305请求者只能使用代理访问请求的网页;307临时重定向
4开头请求报错;400服务器不解,请求语法错误;401需要身份验证;403服务器拒绝请求;404服务器找不到请求的网页;405禁用请求中指定的方法
5开头服务器报错;500服务器内部错误;501服务器无法识别请求方法;502网关错误;503服务不可用;504网关超时;505http版本不受支持
浏览器的缓存
缓存机制:
当查找缓存都没有的时候,才会去请求,缓存查找顺序如下:service worker,memory cache, disk cache, push cache
service worker: 它涉及到请求拦截,所以都用https,它可以自由控制缓存哪些文件,如何匹配、读取缓存;需要先注册Service worker,然后监听install事件后可以缓存需要的文件,下次访问可以通过拦截请求,查看是否存在缓存,如果有,直接读取缓存,否则请求数据
memory cache是内存中的缓存,主要包含当前页面中已经抓取到的资源,比如样式,图片等等,关闭页面后,缓存消失
disk cache是硬盘中的缓存,读取速度慢,但容量和存储时效性较强,它会根据http header的字段判断哪些需要缓存,哪些可以直接使用,哪些需要重新请求,跨站点情况下,相同地址资源如果被硬盘缓存下来,就不会再请求
push cache 推送缓存是http/2中的,以上三中都没有,它才会被使用
HTTP缓存:分为强缓存和协商缓存,强缓存失败时,才走协商缓存
强缓存:根据http头中的expires和cache-control字段控制,如果有直接从缓存中获取资源,不会请求。
服务器返回响应中,在response headerzhong 设置expires字段,当再次请求时,如果本地时间小于expires时间,就读取缓存资源
协商缓存:浏览器需要向服务器询问缓存相关信息,再判断是否重新发起请求,如果服务器提示缓存资源没有改,资源被重定向到浏览器缓存(304状态码)
服务器返回响应中,设置last-modified,随后每次请求,都会带上if-modified-since字段,它的值是上一次请求返回的last-modified,服务器对比,if-modified-since === last-modified, 如果不一样,就会返回完整的响应内容,在response header中添加新的last-modified, 如果一样,返回304, response header不会再添加last-modied字段
缓存使用场景:
1、打开网页,输入网址:查找disk cache是否有匹配,如果有就用, 没有就发请求
2、刷新(F5):t因为ab没有关闭,所以,memory cache被优先匹配,然后disk cache
3、强制刷新(Ctrl+F5):浏览器不适用缓存,因此请求头都带有cache-control:no-cache
怎么设置缓存?
cookie:辨别用户身份,在http请求在头部发给服务端
sessionStorage:浏览器关闭会全部删除
localStorage:.setItem(key,value) 设置记录;.getItem(key)获取记录;.removeItem(key)删除单条记录;.clear()删除所有记录;
application cache离线存储:将大部分图片资源、js、css放在manifest文件配置中,当页面打开时,通过manifest文件来读取本地文件或是请求服务器
Url输入后发生什么
首先会去缓存中查找,是否与要找的相匹配的资源,如果有,从缓存中拿资源,如果没有通过dns将url解析成对应的ip地址,与ip地址对应的服务器建立tcp连接,随后我们向服务端发出http请求,服务器处理完,把数据放在http响应里返回给客户端,浏览器渲染页面:
浏览器缓存——系统缓存——路由器缓存
1、DNS解析;解析ip时,首先向本地dns发出请求,如果找不到,依次向根服务器、顶级域名服务器、权限服务器得到ip,本地dns将ip发回给浏览器,浏览器向ip发出请求
2、TCP连接(三次握手);客户端携带个什么包给服务端;服务端接受,服务端带x包给客户端;客户端接受
3、HTTP请求;
4、服务器响应,数据返回;
5、浏览器拿到响应数据,解析,渲染页面
Ajax、axios、fetch:区别、特点、原理、优缺点、流程
定义: Asynchronous javaScript and XML
优点:不刷新整个页面的情况下与服务器通信保持原有页面状态;异步的
缺点: ajax逻辑会把对客户端的安全扫描技术隐藏起来,允许黑客从远程服务器上建立新的攻击,例如跨站点脚本攻击,SQL注入攻击
$ajax参数:
- url: 请求地址;
- type: 请求类型,
- get/post;
- timeout:设置请求超时的毫秒数;
- async 为true, 所有请求为异步,false是同步;
- data: 发送到服务器的数据,参数;
过程:
- 创建对象,打开浏览器; var xhr = new XMLHttpRequest
- 输入地址: xhr.open(‘post’, ‘1.text’, true)
- 发送请求: xhr.send()
- 等待服务器返回内容: xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status ===200 ){ alert(xhr.responseText) } else { alert(‘出错了’) }
ajax创建:
- 异步向服务器发送请求数据;
- 创建XMLHttpRequest异步调用对象;
- 创建HTTP请求,指定方法、url及验证信息;
- 设置响应HTTP请求状态变化的函数;
- 发送;
- 获取异步返回数据;
- 局部刷新;
ajax、axios、fetch优缺点:
fetch:
缺点:
fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理fetch默认不会带cookie,需要添加配置项。fetch不支持abort中断,不支持超时控制,使用setTimeout及Promise.reject的实现超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费。fetch没有办法原生监测请求的进度,而XHR可以。
优点:
- 更加底层,提供的API丰富(request, response)
- 脱离了XHR,是ES规范里新的实现方式
- 跨域处理(mode为"no-cors")
axios:
优点:
缺点:
- 从浏览器中创建
XMLHttpRequests - 从
node.js创建http请求 - 支持
PromiseAPI - 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换
JSON数据 - 客户端支持防御
XSRF - 只持现代代浏览器.
ajax:
优点:
对原生XHR的封装,做了兼容处理,简化了使用。 增加了对JSONP的支持,可以简单处理部分跨域。
缺点:
- 如果有多个请求,并且有依赖关系的话,容易形成回调地狱。
- 本身是针对MVC的编程,不符合现在前端MVVM的浪潮。
- ajax是jQuery中的一个方法。如果只是要使用ajax却要引入整个jQuery非常的不合理。
React-router、router、hash、history的原理使用
React-router原理:
- 在history库的基础上实现了URL与UI的同步
- 监听url的变化,匹配路由规则,显示相应的页面,而且无需刷新页面跳转;
实现方式:
- hash模式:www.test.com/#/ 就是hash url, #后面哈希值变化时,通过hashchange事件监听url变化,跳转页面;
- history模式: 使用history.pushState和history.replaceState改变url,不会刷新页面,只会更新浏览器历史记录;
两种对比:
- history可以通过api添加任意类型的数据到历史记录中,在用户手动输入地址或者刷新页面时会发起url请求,后端需要配置index.html页面用户匹配不到静态资源的时候;
- hash只能更改哈希值,hash无需后端配置,兼容性好;
React-router原理: 实现URL与UI界面的同步;URL=》location,UI=》component;
具体实现:
- Router与route的区别:
- Route:是进行url和函数的映射;
- Router:在接收到一个url后,去路由映射表中查找相应的函数;
- 客户端路由:路由的映射函数通常进行一些DOM的显示和隐藏操作;基于Hash(#及其后),History API两种方法;
- History三种形式:browserHistory、hashHistory、createMemoryHistory;
react-router依赖的基础是History,是个独立的第三方js库,兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API。具体来说里面的history分为三类:
老浏览器的history: 主要通过hash来实现,对应createHashHistory利用HTML5里面的history pushState、replaceState 高版本浏览器: 通过html5里面的history,对应createBrowserHistory 通过hash来存储在不同状态下的history信息 location.hash=*** location.replace()
node环境下: 主要存储在memeory里面,对应createMemoryHistory在内存中进行历史记录的存储
兼容性问题: 浏览器、前端
| 浏览器兼容性问题 | IE相关兼容性 | css兼容性 |
| img相关图片IE中有边框: img { border: 0/none } 图片下方3像素缝隙:img { display: block }或者img { vertical-align: top/middle } | 默认高度(IE7及以下版本)部分块元素默认高度(16px左右)没有高度,要设置height: 0; | !important不推荐, |
| 表单相关表单元素距离底部间距不一致: input { float: left } | 浮动元素双倍边距(IE6中)浮动元素,margin加倍显示:display: inline | flex |
| 透明度其他浏览器:opacity: 0-1;IE写法:opacity:0-1; filter: alpha(opacity = 50) | input去掉默认边框,不能设置border:none(IE6及以下)border: 0; | css3属性 |
| 浏览器默认的margin和padding不同*{ margin: 0; padding: 0; } | 按照四舍五入解析百分比,容易大于100%给右侧浮动元素: clear: right; |
- safari中伪元素不支持CSS3动画
- safari中元素高度为0,直接被忽略,在IE/chrome中都是作为块级看待,有相应的位置
- IOS系统中,浏览器只支持给原生HTML按钮或《a》标签加js事件
- Safari中Date.parse()解析时间字符串,格式必须是YYYY/MM/DD HH:MM:SS
- IOS系统中,H5播放器不支持自动播放
- 用原生js写粘贴复制到剪贴板的时候,采用了很多方法,比如document.execCommand(‘copy’) 写了很多形式,就是不好使,后来google搜索才知道,不兼容chrome,只支持IE,这个浪费了很多时间,影响开发效率,百度搜索的问题;
- PropTypes不好用的时候,把import PropTypes from 'react' 写成 import PropTypes from 'prop-types' ,把defaultPropTypes 改成 propTypes
- 开发过程中,遇到了一个常见的兼容性问题: IOS不识别 ' 2018-12-13 '中的 ' - ',需要转为2018/12/13的形式才可以识别;
- 开发过程中,写了两个定时器,在两个定时器需要在某个条件下,替换的时候,需要clearInterval清除定时器,要不然会出现,每秒会相继执行两个定时器的现象;
- 不要在componentWillRecivieProps里使用setState, 如果要使用,需要判断结束条件,不然会出现无限重渲染,导致页面奔溃;
- 画布节点拖拽卡顿,用的lodash的throttle方法控制节流,减少setState的次数;
- 前端用的是history跳转的,但是url地址页面一刷新就报错,后来后端那边设置了一判断处理,才可以的;
线程、进程
进程: 一个完成的任务;比如,调用数据库
线程: 完成这个任务的诸多子任务之一;比如要从数据库中产生一份统计表,上传到某文件;
一个线程只属于一个进程,一个进程可以有多个进程;
线程好处:提高并发性;
节流、防抖
| 名称 | 原理 | 适用场景 | 实现 |
|---|---|---|---|
| 防抖 | 当事件触发n秒后执行回调,如果在n秒内又被触发,则重新计时. | 1.按钮提交场景:防止多次提交,只提交最后一次. 2.搜索框联想场景:防止联想发送请求,只发送最后一次输入. | 1.非立即执行 2.立即执行 |
| 节流 | 规定在一个单位时间内只能触发一次函数.如果在单位时间内触发多次,只执行一次. | 1.拖拽场景:固定时间只执行一次,防超高频次触发. 2.缩放场景:监控浏览器resize,scroll | 1.时间戳实现 2.定时器实现 |
节流实现: 防抖实现:
编辑
垃圾回收、内存泄漏、call/applay
内存泄漏:
- 闭包return 给window;
- 未声明的全局变量;
- 定时器没有及时clear;
- vue 中在mounted/created 用$on;
- 给DOM对象添加的属性时一个对象的引用;
- DOM对象与JS对象相互引用;
- 反复写同一个属性会造成大量内存占用;
避免内存泄漏:
尽量少使用闭包;及时删除监听器;
垃圾回收机制:
垃圾回收器根据根开始标记,然后访问并标记来自他们的引用,直到有未访问他们的引用为止,删除所有没标记的对象;
call/apply:
call: 参数逐个列举
apply: 参数数据
事件委托、事件监听、事件处理函数、作用域、声明提升
函数声明提升权重大于变量声明提升,函数有声明提升,函数表达式没有声明提升
事件委托/代理:
- 利用事件冒泡原理,让自己所触发的事件,让父元素代替执行;
实现原理:
- event.target监听实际触发元素;避免是期望元素的子节点,需追加parentNode循环判断。
好处:
- 提高性能、提高事件的处理速度,减少内存占用;
- 动态添加DOM元素,不要因为元素的改动而修改事件绑定
事件监听:
- 有三个阶段,捕获、目标、冒泡;
- 优点:可绑定多个事件,可解除相应的绑定
事件处理函数:
- 处理用户操作的函数,不同操作,不同名称;
方法:
- DOM直接绑定,比如onCLick;
- 在javaScript代码中绑定;
- 绑定事件监听函数,比如addEventListner()、 attachEvent();
作用域:
- 全局作用域、函数作用于、eval作用域;没有块级作用域;
作用域链:
- 当函数被创建,就有了作用域,当被调用,就有了作用域链,当被继承,就有了原型链,当需要获取作用域链或原型链上的变量或值时,就有了闭包;
继承、闭包、原型、原型链、面向对象、循环
闭包:
- 定义:能读取其他函数内部变量的函数
- 作用:读取函数内部变量的值
- 缺点: 变量是保存在内存中,内存消耗大,所以会造成网页的性能问题;
- 解决/注意:在退出函数前,将不适用的变量全部删除;
继承:
- 定义:子类有父类的所有属性和方法
- 优点: 抽取重复代码,减少代码冗余
- 缺点: 代码耦合性太强
继承方式:
- 构造函数式:借用call或apply方法,把父类构造函数复制继承到子类上,子类new出的实例,就是把父类构造函数的内容copy到实例中,所以每个实例都是独立的,私有的;
缺点:只实现属性的私有,没有实现方法共享
- 原型链式: 借用js对象的特性,对象在寻找自己属性时,先在当前对象上找,没有,再去自己原型链上找,一直向上找直到null
好处:节省内存
缺点:属性和方法全部都被共享了
- 组合式(原型链+构造函数): 基本属性放父类的构造函数里;共享的函数方法放在父类原型上
优点:实现函数共享,属性私有
- Object.create()寄生式
- 寄生组合式
面向对象:
三大特征:
- 继承;目的: 实现代码复用;注:父类的私有属性private和构造方法不能被继承;子类可以写自己特有属性和方法,实现功能的扩展,子类可以复写父类的方法;protected属性对外界隐藏,允许子类访问;
- 封装;目的: 增强安全性和简化代码,使用者不需要了解具体实现细节,只要通过外部接口,来使用;
- 多态;可扩展,增强维护性;
创建对象的方式:
- 对象字面量:var a={}
- 用面向对象的方法: var obj=new Object()
- 构造函数方式 function Abc(){} var c=new Abc() 构造函数首字母大写 优化:把方法放在原型上,,把属性放在构造函数上,把共有属性放在init方法函数中,也在放到原型上,这样避免内存浪费,方法可以共有;
创建对象的模式:
- 工厂方式
- 构造函数方式
声明组件的方式
- 无状态组件,又叫纯组件SFC
- React.creactClass
- React.component ES6 class…extends
ui组件负责ui的呈现,容器组件负责管理数据和逻辑;二者通过react-redux提供的connect方法联系起来;
调用super(props)之前,子类不能使用this, 调用super(props)便于子类在constructor中访问this.prps;
有无状态组件、受控非受控组件:
| 有状态组件 | 无状态组件 | 受控组件 | 非受控组件 |
| 在内存中存储有关组件状态变化的信息 | 计算组件的内部的状态 | 没有维持自己的状态 | 保持自己的状态 |
| 可以改变状态 | 不能改变状态 | 数据由父组件控制 | 数据由dom控制 |
| 包含过去,现在,未来可能的状态变化情况 | 不包含过去,现在和未来可能发生的状态变化情况 | 通过props获取当前值,通过回到通知更改 | refs用于获取当前值 |
| 接受无状态组件状态变化要求的通知,然后将props发给他们 | 从有状态组件接受props并将其视为回调函数 |
判断一个类是否继承另一个类的方法
Webpack、gulp:区别、特点
前端优化、react优化、vue优化、性能优化、webpack优化
| 前端优化 | webpack优化 | react优化 | vue性能优化 |
| 加快首屏渲染非核心代码异步加载脚本async:加载完后立即执行,如果是多个,执行顺序和加载顺序无关 | 开发阶段的构建性能:减少模块解析:如果模块中没有其他依赖,比如打包好的第三方库jq,就不需要解析,在module中设置noParse: /jq/优化loader性能; | 避免重复渲染;shouldComponentUpdate判断是否执行render | |
| 资源合并压缩合并图片,css,js文件,压缩js: UglifyPlugin; css: MiniCssExtractPlugin;Html:HtmlWebpackPlugin现流行gzip压缩,在http请求头中Accept-encoding添加gzip标识,需要服务器支持这一功能,提交可以较少50%左右图片较多的使用懒加载优化 | 提取第三方库:webpack4的splitChunk插件cacheGroups选项使用cdn引入,jq、echarts这种库将资源下载到服务器引入:webpack配置externals: { jquery: ''$', echarts: 'echarts',} | useMemo指定依赖项,变化时才计算const result = useMemo(()=>computeExpensiveFunc(start), [start]); | |
| 减少http请求次数和请求时间一个域名对应多个相同服务的ip | 服务端给客户端传输性能,代码少,时间少,文件越少,http请求越少 | 合理使用useCallback组件绑定的函数在每次render都是新生成的,所以使用useCallback并添加依赖项 | |
| 使用cdn解析ip时,向本地dns发请求;本地dns向根、顶级域名、权限服务器发请求,得到全局负载均衡系统(gslb)的ip地址;本地dns向gslb发请求,gslb根据本地dns的ip地址判断用户的位置,筛选距离用户最近的本地负载均衡系统(slb),gslb将slb的ip发给本地dns;本地dns发给浏览器,浏览器向slb发请求;slb选出最优的缓存服务器发给浏览器;浏览器根据slb发回的地址重定向到缓存浏览器;缓存浏览器如果有资源,发给浏览器,没有就向源服务器请求资源,再发给浏览器并缓存在本地; | 体积优化,代码压缩,插件使用:optimization: { minimize: true, minimizer: { new OptimizeCssAssetsPlugin()}}js: UglifyPlugin;css: MiniCssExtractPlugin;Html:HtmlWebpackPlugin;gzip,是一种压缩文件的算法,文件过大就可以用它压缩, 在http请求头中Accept-encoding添加gzip标识,需要服务器支持这一功能,提交可以较少50%左右;懒加载; | 谨慎使用context,它是跨组件传值,所以无法阻止context触发的rendercontext只放在必要的关键的,被大多数组件共享的状态建议在负极获取context数据,通过props传递 | |
| 利用浏览器缓存强缓存:不请求,直接使用本地缓存协商缓存:1、第一次请求资源,服务器返回,带上last-modifiedhed在response header中,浏览器再次请求时,会在requset中家加上if-modified-since = last-modified,服务器对比,没变化返回304,有变化,就返回资源内容2、Etag、if-none-match第一次请求,服务返回Elag,字符串,资源有变化,Etag就不同,再次请求时,加if-none-match = Etag, 服务器对比,没变化,返回304,有变化,返回资源内容 | 热更新webpack-dev-server:代码变动时,浏览器会刷新,重新请求所有资源,但使用热更新后,代码修改时,浏览器不刷新,局部进行替换,devServer: { hot: ture }plugins: [new webpack.HotModuleReplacementPlugin()]写入文件中if (module.hot){ module.hot.accept() }热更新原理:webpack-dev-server会向打包结果注入module.hot属性,正常情况下,不管是否有热更新,重新打包都会调用location.reload刷新页面,但如果执行module.hot.accept()就不会调用它了,而是使用websoket的方式,将新内容传给浏览器,只是修改的部分,然后将结果交给插件hotModuleReplacementPlugin注入的代码执行,它会覆盖原始代码,重新执行 | redux使用要小心,否则触发无用的render | |
| css放文件头部,js文件放底部第一时间加载可以看到样式,js也可以放在头部,加上defer属性,异步下载,延迟执行 | 异步处理loader,减少处理时间;thread-loader会把loader放在一个线程中运行,提高构建效率 | 操作redux源数据时,数组或对象地址是引用类型,如果直接操作,array.push(xx), 这样不会改变数据的地址,是直接修改的是地址指向的堆中的真实数据,仍然是相等的 | |
| 图片延迟加载页面中,先不给图片设置路径,当图片出现在可视区域时,才去加载真正的图片 | 尽量少的使用不同的工具:plugin加载都有启动时间 | ||
| 减少重排重绘回流(重排):改变dom元素位置、大小、内容改变,添加删除dom元素,浏览器窗口尺寸改变,需要重排,重排一定需要重绘;重绘:重新绘制界面,样式改了,需要重绘,重绘不一定重排减少方法:1、用js修改样式时,不用直接写样式,替换class修改样式2、将dom脱标, | 减少编译的大小:使用更小、更少的库多页面应用程序中使用commonChunkPlugin多页面以async使用commonCHunckPlugin移除不使用的代码: tree shaking,(webpack2开始支持) 生产环境自动开启,但没有提供普通的es6方式导入,通过commonjs方式导出的,无法发回作用只编译当前正在开发的代码tree shaking原理:webpack从入口开始寻找依赖关系,解析模块时,根据es6模块导入语句来判断,谁依赖谁,根据导出是否被使用,标记未使用的导出为dead code,然后交个代码压缩功能句处理,它会移除 | ||
| 少些if-lese-,用switchif else 会执行多次判断,switch只需要一次 | dllPlugin和ddlReferencePlugin拆分bundles提升构建速度,将一些不常更新的依赖提前打包引入entry: {vendor: ['react, 'redux', 'react-router',‘axios’,]}plugin: [ new webpack.DllPlugin({ name: 'xx' 需要和outPut内的liabrary保持一致 patch: patch.resolve(_dirname, 'dist', 'mainfest.json') 生成mainfest.json文件,})] |
算法、排序
基本排序:
- 冒泡排序:从头开始,两个两个互相比较,小的放前面;
- 选择排序:从头开始,第一个数与后面所有相比,最小的放第一个位置;
- 插入排序: 第一个放哪里无所谓,接下来比第一张小,放左边,依次进行;
高级排序:
- 快速排序:采用递归方式,随意找到一个数,小的放前面,大的放后面,分别对前后做相同的操作比较;
- 希尔排序:插入排序的改良算法,但与其核心概念不同,先从比较远的开始比较,小的放在前面;
高阶函数(HOC)
参数为一个组件,返回为一个组件
Amd/Cmd
两者对模块执行时机不同:
AMD(require.js): 加载完模块,立即执行;
COD:不会立即执行,等到遇到require才执行
单页面应用(SPA)、优缺点、实现方式
单页面应用(SPA):只有一个主页面的应用,所有页面内容都包含在这个所谓的主页中,在交互的时候,由路由程序动态载入,单页面跳转,仅仅刷新局部资源,多用于pc端
多页面应用(MPA):一个应用中有多个页面,页面跳转的时候,整页进行刷新
单页面缺点: 没有前进和后退功能,需要自行实现前进后退
Git
git常用命令
git log 查看日志 git add . 提交当前目录全部文件 git reset --hard xxx 本地回退到某版本
git status 查看冲突 git commit -m 提交到本地 git rm xx 删除文件
git diff 查看修改 git push origin xx 提交到远程 git checkout -b 新建分支
git branch 查看分支 git branch -D 删除本地分支 git push origin --delete xx 删除远程分支
git stash 暂存区 git stash pop 回复暂存区的代码删除暂存
网络安全、xss攻击
xss攻击:跨站脚本攻击,攻击者在另外一个用户的浏览器中执行恶意代码脚本注入
持续性攻击:通过表单提交、评论方式将提交到网站,如果服务端没有做任何处理,直接把数据返回前端,前端展示在页面中,所有的用户打开页面,就会弹出这个弹框
防止:校验用户输入和请求,客户端和服务端必须验证
小程序
Node
Js、d3、svg、echarts、highcharts、ant-g6、mxgraph
以上为个人查询文档资料思考所总结,如果错误,请各位大佬指正,非常感谢!以上多个部分还未完善,后续抽时间会继续补充完整