前端flex
flex-shrink 固定位置
flex-wrap 换行
前端发送总结
Pubsub.js
publish(‘type’,data) 发布消息
subscribe(‘type’,(type",data)=>{})
redux
store.dispatch({type:‘’,data})
store.subscribe()
store.getState()
跨域
虚拟dom
首先,代码初次运行,会走生命周期,当生命周期走到created到beforeMount之间的时候,会编译template模板成render函数。然后当render函数运行时,h函数被调用,而h函数内调用了vnode函数生成虚拟dom,并返回生成结果。故虚拟dom首次生成。
之后,当数据发生变化时会重新编译生成一个新vdom。再后面就等待新 旧两个vdom进行对比吧。我们后面就继续说对比的事情。
声明,下面所说的sel选择器相同,指的是标签名,id,class都相同。
例如
如果节点相同,那么进去第二部分,即比较两个节点的属性是否相同,节点是否存在文本,文本是否相同。是否存在子节点,子节点是否相同。这部分主要在patchVnode中执行
那么,在第二部分,会做哪些事情呢。
1、如果存在文本时,更新文本
2、如果存在属性时,更新属性
3、如果存在子节点时,更新子节点
1、如果旧vnode上存在,而新vnode上不存在,那么执行删除操作
2、如果旧vnode上不存在,而新vnode上存在,那么执行新增操作
3、如果新旧vnode上都存在,那么执行替换操作(即,新增新的,删除旧的),文本,和属性的替换是在这部分完成。而对于子节点,如果新vnode和旧vnode上都存在子节点时,那么会进入第三部分比较。比较子节点的差异。
第三部分,主要在updateChildren函数中执行,主要用于比较某个节点下的子节点差异。而在这里,就要用到diff的一个算法了。具体怎么算。我们后面详细说updateChildren时再说。
h 函数
patch 函数
diff的过程,就是一个 patch —> patchVnode —> updateChildren —> patchVnode —> updateChildren —> patchVnode… 这样的一个循环递归的过程
vue: 了解vueMVVM原理的人应该都清楚,vue通过Object.defineproperty的数据劫持,会劫持到每一个状态数据,给他们加上getter,setter。并且创建一个发布者Dep,同时,会给依赖这个状态数据的每个依赖者添加一个订阅者watcher。这样,当数据发生变化时,会触发对应的setter,从而Dep会发布通知,通知每一个订阅者watcher,然后watcher更新对应的数据。但是,如果任何一个数据的依赖我都增加一个watcher。那么项目中的watcher数量是会非常庞大的。细粒度太高,会带来内存和依赖关系维护的巨大消耗。这样一种情况下,vue采用响应式+diff的方式。通过响应式的getter,setter快速知道数据的变化发生在哪个组件中,然后组件内部再通过diff的方式去获取更详细的更新情况,并更新数据。
react: 而react却是通过他的一个生命周期函数shouldComponentUpdate实现的。通过手动在这个生命周期函数中判断当前组件的数据是否有发生变化,来决定当前组件是否需要更新。这样,没有发生状态数据变化的组件就不需要进行diff。从而缩小diff的范围。
事件
宏任务:setTimeout、setInterval、Ajax、DOM事件【W3C规范】
微任务:Promise、async/await【ES规范】
微任务执行时机比宏任务早
微任务在DOM渲染前触发 【Promise】
宏任务在DOM渲染后触发 【setTimeout】
回调栈 Call Stack
事件循环 event loop
回调队列 Callback Queue
微任务队列 micro task queue
同步代码,一行一行放在回调栈中执行,执行完了就出栈
遇到异步,记录下来,等待时机;时机到了,就移动到回调队列中
当回调栈为空,(微任务[微任务队列])【尝试DOM渲染】 事件循环开始工作:轮询查找(宏任务)回调队列,有则移动到回调栈中执行
继续轮询loop
实际上真正的 event loop 是这样的
一开始整个脚本作为一个宏任务执行
执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列
当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完
执行浏览器UI线程的渲染工作
检查是否有Web Worker任务,有则执行
执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空
所以过程是
【宏任务(代码整体)——同步任务——微任务——DOM渲染】——宏任务——同步任务——微任务——DOM渲染…
介绍一下 XSS 攻击和 CSRF?
-
XSS(跨站脚本攻击),是一种代码注入攻击,是通过在网站中注入恶意代码达到劫持用户 cookie 或其他信息的一种攻击。
-
客户端:限制输入长度
-
上线前:使用扫描工具自动检测 XSS 漏洞
-
CSRF(Cross-site request forgery)跨站请求伪造
-
服务端做一些防御操
XSS攻击
Cross Site Script Attack
a标签
img url 注入
它能够检测到存在于 HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 JavaScript 字符串、内联 CSS 样式表等多种上下文中的 XSS 漏洞,也能检测 eval()、setTimeout()、setInterval()、Function()、innerHTML、document.write() 等 DOM 型 XSS 漏洞,并且能绕过一些 XSS 过滤器。
url 参数注入
防范存储型和反射型 XSS 是后端 RD 的责任。而 DOM 型 XSS 攻击不发生在后端,是前端 RD 的责任。防范 XSS 是需要后端 RD 和前端 RD 共同参与的系统工程。
转义应该在输出 HTML 时进行,而不是在提交用户输入时。
业务 RD 需要选取合适的转义库,并针对不同的上下文调用不同的转义规则。
- 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
在内联的 - JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
- 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
- 在标签的 href、src 等属性中,包含 javascript: 等可执行代码。
- 在 onload、onerror、onclick 等事件中,注入不受控制代码。
在 style 属性 - 和标签中,包含类似 background-image:url(“javascript:…”); 的代码(新版本浏览器已经可以防范)。
- 在 style 属性和标签中,包含类似 expression(…) 的 CSS 表达式代码(新版本浏览器已经可以防范)。
原则减少漏洞的产生:
利用模板引擎
开启模板引擎自带的 HTML 转义功能。例如:
在 ejs 中,尽量使用 <%= data %> 而不是 <%- data %>;
在 doT.js 中,尽量使用 {{! data } 而不是 {{= data };
在 FreeMarker 中,确保引擎版本高于 2.3.24,并且选择正确的 freemarker.core.OutputFormat。
避免内联事件
尽量不要使用 onLoad=“onload(‘{{data}}’)”、onClick=“go(‘{{action}}’)” 这种拼接内联事件的写法。在 JavaScript 中通过 .addEventlistener() 事件绑定会更安全。
避免拼接 HTML
前端采用拼接 HTML 的方法比较危险,如果框架允许,使用 createElement、setAttribute 之类的方法实现。或者采用比较成熟的渲染框架,如 Vue/React 等。
时刻保持警惕
在插入位置为 DOM 属性、链接等位置时,要打起精神,严加防范。
增加攻击难度,降低攻击后果
通过 CSP、输入长度配置、接口安全措施等方法,增加攻击的难度,降低攻击的后果。
主动检测和发现
可使用 XSS 攻击字符串和自动扫描工具寻找潜在的 XSS 漏洞。
节流防抖
节流:多次事件按照时间做平均分配触发
防抖:多次事件一次响应的情况
http 三次握手以及常见的状态码
-
第一次握手是客户端给服务端发送请求,请求建立连接。
-
第二次握手是服务端给客户端发送请求,表示已经收到客户端的请求,并且同意建立连接。
-
第三次握手是客户端向服务端发送请求,表示确认收到服务端发送的信息。
-
三次握手的原因是为了确认客户端和服务端都有收发信息的能力,少一次确认不了,多一次浪费资源。
四次挥手
- 第一次挥手:先由客户端向服务器端发送一个 FIN,请求关闭数据传输。
- 第二次挥手:当服务器接收到客户端的 FIN 时,向客户端发送一个 ACK,其中 ack 的值等于 FIN+SEQ
- 第三次挥手:然后服务器向客户端发送一个 FIN,告诉客户端应用程序关闭。
- 第四次挥手:当客户端收到服务器端的 FIN 是,回复一个 ACK 给服务器端。其中 ack 的值等于 FIN+SEQ
浏览器渲染引擎的工作原理和工作流程?
-
解析 HTML 文档,构建 DOM 树(DOM 节点树。
-
解析 CSS 文档,生成 CSS 规则树。
-
合并 DOM 树和 CSS 规则树,生成渲染树 render 树。
-
布局 render 树,计算每个元素的大小,位置等信息(重排会走这一步)。
-
绘制 render 树,绘制页面的像素信息,(根据 render 树上每个节点的几何属性计算每个节点的像素数,重绘会走这一步)
-
浏览器会将各层节点的像素信息发给 GPU,GPU 将各层进行合成和渲染,最终展示到页面上。
浏览器安全问题,https 协议,https 与 http 区别
-
HTTP 协议工作在 80 端口,HTTPS 协议工作在 443 端口
-
HTTPS 需要申请证书(用于验证服务器身份)
-
HTTP 在 TCP 三次握手建立连接之后即可开始传输数据;HTTPS 协议则需要在建立 TCP 连接之后客户端与服务器在进行 SSL 加密,确定对话密钥,完成加密后才开始传输数据。
-
HTTPS 协议协议:是具有安全性的ssl加密传输协议,为浏览器和服务器之间的通信加密,确保数据传输的安全;
HTTP 协议:是超文本传输协议,信息是明文传输;
什么是异步加载?异步加载和延迟加载有什么区别?
异步加载时相对于同步加载而言的,我们平常书写的代码就是同步加载,代码自上而下执行,是阻塞式的,而异步加载是非阻塞式的,在执行同步代码时,并不会阻塞我后续代码的执行,(例如定时器,发送 ajax 请求),而延迟加载则是一开始并不加载,在我需要的时候再进行加载(例如图片的懒加载)
回流和重绘
回流一定会触发重绘,但是重绘不一定会引起回流
改变页面布局或者大小尺寸的时候会引起回流,反之就是重绘
重绘:当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新 ,UI 层面, 例如改变元素颜色
回流:又叫重排(layout)。当元素的尺寸、结构或者触发某些属性时,浏览器会重新渲染页面,称为回流
块元素
div dl form h1 h2 h3 h4 h5 h6 hr ol li p pre table td tr
行内元素
a b s i u span br img input textarea sub sup
行内元素和块级元素 空元素的特点
行内元素:
1.无法设置宽高;
2. 对margin仅设置左右有效,上下无效;
3. padding上下左右有效;不会自动换行
块级元素:
1.可以设置宽高
2. margin和padding的上下左右均对其有效
3. 超出当前行会自动换行
4. 多个块状元素标签写在一起,默认排列方式为从上至下
img:属于行内块元素(inline-block),即有行内元素的属性也有块级元素的属性
元素之间的转化可以通过设置样式:display:block/inline/inline-block来改变自身的元素属性
空元素:
没有闭合标签的标签被称作为空标签。<br/> <hr/>
在我们使用的标签中,有的具有闭合标签<td></td>
vue双向绑定
1、vue双向数据绑定原理,又称vue响应式原理,是vue的核心,双向数据绑定是通过数据劫持结合发布者订阅者模式的方式来实现的,通过Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变
2、vue实现双向数据绑定的核心是Object.defineProperty()方法
3、Object.defineProperty(obj, prop, descriptor)方法,接收三个参数,分别为obj(定义其上属性的对象)prop(定义或修改的属性)descriptor(具体的改变方法),就是用这个方法来定义一个值,当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法
vue.config.js 报错页显示
client: {
overlay: false,
},