三栏布局
- float
<div> <section class="a1">a1</section> <section class="a2">a2</section> <section class="a3">a3</section> <section class="a4">a4</section> <section class="a5">a5</section> </div> div { width: 180px; height: 50px; } section { float: left; } .a1 { width: 50px; height: 50px; background-color: tan; } .a2 { float: right; width: 50px; height: 50px; background-color: tan; } .a3 { width: 80px; height: 25px; background-color: red; } .a4 { width: 40px; height: 25px; background-color: #ddd; } .a5 { width: 40px; height: 25px; background-color: #666; }
- position
div { width: 180px; height: 50px; position: relative; } .a1 { position: absolute; width: 50px; height: 50px; background-color: red; } .a2 { position: absolute; left: 50px; width: 80px; height: 25px; background-color: blue; } .a3 { position: absolute; left: 50px; top: 25px; width: 40px; height: 25px; background-color: green; } .a4 { position: absolute; left: 90px; top: 25px; width: 40px; height: 25px; background-color: tan; } .a5 { position: absolute; width: 50px; height: 50px; left: 130px; background-color: red; }
- flex
div {
width: 180px;
height: 50px;
display: flex;
flex-flow: column wrap;
align-content: flex-start;
}
.a1 {
width: 50px;
height: 50px;
background-color: red;
}
.a2 {
width: 80px;
height: 25px;
background-color: tan;
}
.a3 {
flex-grow: 1;
background-color: aqua;
}
.a4 {
width: 25px;
height: 50px;
background-color: #fff;
}
.a5 {
flex-grow: 1;
background-color: red;
}
- 三栏等宽布局
div {
width: 180px;
height: 50px;
display: flex;
background-color: tan;
}
section {
flex: auto;
}
.a1 {
background-color: #fff;
}
.a2 {
background-color: #444;
}
.a3 {
background-color: red;
}
垂直居中
- position
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
- table
div {
width: 100px;
height: 100px;
position: relative;
background-color: tan;
display: table-cell;
vertical-align: middle;
text-align: center;
}
span {
background-color: red;
}
- 行内块
div {
width: 100px;
height: 100px;
position: relative;
background-color: tan;
}
section {
width: 50px;
height: 50px;
display: inline-block;
margin: 25px;
background-color: red;
}
- float
div {
width: 100px;
height: 100px;
position: relative;
background-color: tan;
}
section {
width: 50px;
height: 50px;
margin: 25px;
float: left;
background-color: red;
}
- line-height
div {
width: 100px;
height: 100px;
background-color: tan;
text-align: center;
line-height: 100px;
}
span{
background-color: #fff;
vertical-align: middle;
}
盒模型
margin-box, border-box, padding-box, content-box
首先是最内层content-box,用来显示元素信息
向外是padding-box,主要用于设置元素四个方向的内边距,
再向外是border-box,用于设置元素四个方向的边框样式,
最外层是margin-box,为了让元素与其他元素隔开,对于垂直方向上的BFC元素的margin会发生合并,去较大的值
padding-box和margin-box是透明的,padding-box会受元素的背景的影响,可以通过box-sizing设置
padding-box和border-box不能去负值,margin-box可以取负值
还有元素的溢出属性,处理空白空间及文本溢出
* css中每个元素都看作多个盒子的组合,我们可以通过设置这些盒子的属性来改变元素的样式
* 如果设置 box-sizing 为 content-box,那么宽度就是内容区的宽度
* 如果设置为 border-box,那么宽度就死活内容区宽度+padding+border
单行文本溢出省略:
text-overflow:ellipsis;
white-space:nowrap;
overflow:hidden;
BFC
浮动,绝对定位,overflow不为visible,非块级盒子块级容器
触发:
1. float 除了none以外的值
2. overflow 除了visible 以外的值(hidden,auto,scroll )
3. display (table-cell,table-caption,inline-block, flex, inline-flex)
4. position值为(absolute,fixed)
特性:
在BFC中,盒子从顶端开始垂直地一个接一个地排列。
盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻盒子垂直方向的margin会发生重叠。
在BFC中,每一个盒子的左外边距(margin-left)会触碰到容器的左外边缘(border-left)。
BFC不会与浮动盒子产生交集,而是紧贴浮动元素边缘。
计算BFC高度BFC时,自然也会检测浮动的子盒子高度。
应用:
自适应两栏布局
解决margin叠加问题:下面元素添加父元素:overflow: hidden;
清除浮动,计算BFC高度
闭合浮动的办法:
- 包含块overflow:hidden/BFC
- 包含块display:flow-root/BFC
- 包含块变表格/BFC
- 包含块变行内块元素/BFC
- br标签的清除浮动
谈谈你对MVVM开发模式的理解
- MVVM主要分为model/view/viewmodel三部分
- model:代表数据模型,数据和业务逻辑都在model层中定义
- view:代表UI视图,负责数据的展示
- viewmodel:负责监听model中数据的改变并且控制视图的更新,处理用户交互操作
- Model和View并无直接关联,是通过viewmodel来进行联系的,model和viewmodel之间有着双向数据绑定的联系。因此当model中的数据改变时会触发view层的刷新,同样view中由用户交互操作而改变的数据也会在model中同步。
- 这种模式实现了model和view的数据自动同步,因此开发者只需要专注于对数据的维护操作即可,而不需要自己操作DOM
如何优化SPA应用的首屏加载速度慢的问题
- 将公用的JS库通过script标签外部引入,让浏览器并行下载资源文件,提高下载速度;
- 在配置路由时,页面和组件使用懒加载的方式引入,在调用某个组件时再加载对应的js文件;
- 加一个首屏 loading 图,提升用户体验;
跨域(Cross-Origin)
只要协议、主机、端口不一致,就会有跨域的问题
- javascript跨域通信
- jsonp
- CORS设置跨域头
- 在框架中配置跨域代理
- jsonp的实现原理
- script标签引入外部网站的代码,一般都是使用查询字符串告诉对方我们页面中的callback函数,然后对方把需要返回的数据包在这个函数里面
- 其实JSONP并不算真正意义上的AJAX请求,只是请求了一个js文件并且执行了,而且这种跨域方法只能进行GET请求
function jsonp(url, value, cb) {
let cbName = 'JSONP_CALLBACK_' + Date.now() + '_' + Math.random().toString().slice(2)
window[cbName] = cb
url = url + '?q=' + value + '&callback=' + cbName
let script = document.createElement('script')
script.src = url
script.onload = () => {
document.body.removeChild(script)
delete window[cbName]
}
document.body.appendChild(script)
}
function ajax(url = '', data = {}, type = 'GET') {
if (type === "GET") {
let urlStr = ""
Object.keys(data).forEach(key => {
urlStr += key + '=' + data[key] + '&'
})
if (urlStr) {
urlStr = urlStr.substring(0, urlStr.length - 1)
url += '?' + urlStr
}
return axios.get(url)
} else if (type === "POST") {
return axios.post(url, data)
}
}
- CORS
- 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
- 简单请求
- 请求方法为HEAD、GET或者POST中的一种
- HTTP的头信息有以下几种字段Accept、Accept-Language、Content-Language、Last-Event-ID
- Content-Type的值只限于application/x-www-form-urlencoded、multipart/form-data、text/plain三个
- 浏览器发出请求时,浏览器会自动在请求头中添加一个字段Origin,值为发出请求网页的源地址
- 服务端根据这个值,决定是否同意这次请求,如果Origin的值不在指定的许可范围,浏览器接收到的HTTP回应将不包含Access-Control-Allow-Origin,抛出错误被XMLHttpRequest的onerror回调函数捕获。如果Access-Control-Allow-Origin字段正好跟带过去的Origin的值一样,则返回对应的数据,完成一次请求。
- 非简单请求以及option请求
- 非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
- 在进行非简单请求之前,浏览器会在正式请求之前发送一次预检请求,这就是有时候我们会在控制台中看到的option请求,就是说,正式请求之前,浏览器会去问服务端我这个地址能不能访问你,如果可以,浏览器才会发送正式的请求,否则报错。
- 总结
- CORS实现跨域的方法就是根据请求头的Origin值和响应头的Access-Control-Request-Headers和Access-Control-Request-Method的值进行比对,通过了就可以请求成功,没通过就请求失败。
- 比较
- JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
前端如何优化网站性能
- 减少 HTTP 请求数量:
- 浏览器与服务器主要是通过 HTTP 进行通信。浏览器与服务器需要经过三次握手,每次握手需要花费大量时间。而且不同浏览器对资源文件并发请求数量有限,一旦 HTTP 请求数量达到一定数量,资源请求就存在等待状态,因此减少 HTTP 的请求数量可以很大程度上对网站性能进行优化。
- CSS Sprites:
- 国内俗称 CSS 精灵,这是将多张图片合并成一张图片达到减少 HTTP 请求的一种解决方案,可以通过 CSS background 属性来访问图片内容。这种方案同时还可以减少图片总字节数。
- 合并 CSS 和 JS 文件:
- 现在前端有很多工程化打包工具,如:grunt、gulp、webpack等。为了减少 HTTP 请求数量,可以通过这些工具再发布前将多个 CSS 或者 多个 JS 合并成一个文件。
- 采用 lazyLoad:
- 俗称懒加载,可以控制网页上的内容在一开始无需加载,不需要发请求,等到用户操作真正需要的时候立即加载出内容。这样就控制了网页资源一次性请求数量。
- 利用浏览器缓存
- 浏览器缓存是将网络资源存储在本地,等待下次请求该资源时,如果资源已经存在就不需要到服务器重新请求该资源,直接在本地读取该资源。
- 减少 DOM 操作,达到减少重排(Reflow)
- 基本原理:重排是 DOM 的变化影响到了元素的几何属性(宽和高),浏览器会重新计算元素的几何属性,会使渲染树中受到影响的部分失效,浏览器会验证 DOM 树上的所有其它结点的 visibility 属性,这也是 Reflow 低效的原因。如果 Reflow 的过于频繁,CPU 使用率就会急剧上升。
Less / Sass
Less的变量名使用@符号开始
Sass的变量是必须$开始
- 作用域:
- Sass无全局变量概念
- LESS中的作用域和其他程序语言中的作用域非常的相同
- 混合(Mixins):
- Sass
声明:@mixin a($borderWidth:2px){} 调用:@include error();
- Less
声明:.error(@borderWidth:2px){} 调用:.error();
- 继承
- Sass
@extend .block; /*继承.block选择器下所有样式*/
- Less
.block;/*继承.block选择器下所有样式*/
AntDesign / bootstrap
http协议
- HTTP是基于TCP/IP通信协议来传递数据
- HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。HTTP是一个无状态的协议。
- 工作过程大概如下:
- 用户在浏览器中键入需要访问网页的URL或者点击某个网页中链接;
- 浏览器根据URL中的域名,通过DNS解析出目标网页的IP地址;
- 在HTTP开始工作前,客户端首先会通过TCP/IP协议来和服务端建立链接(TCP三次握手)
- 建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可内容。
- 服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
- 一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码:Connection:keep-alive,TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
- 短连接:建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接,如果客户请求频繁,将在TCP的建立和关闭操作上浪费较多时间和带宽。
- 长连接:建立连接——数据传输...(保持连接)...数据传输——关闭连接
- with pipeling: 每次建立链接后无需等待请求回来就可以发送下一个请求
- without pipeling: 客户端只在收到前一个请求的响应后,才发出新的请求。
- Http请求报文
客户端发送一个HTTP请求到服务器的请求消息包括以下格式: 请求行(request line)、请求头部(header)、请求体组成 请求行: 方法: GET 获取资源 POST 向服务器端发送数据,传输实体主体 PUT 传输文件 HEAD 获取报文首部 DELETE 删除文件 OPTIONS 询问支持的方法 TRACE 追踪路径 URL 协议/版本号 请求头: 通用首部(General Header) 请求首部(Request Header) 响应首部(Response Header) 实体首部(Entity Header Fields) 请求体
- Http响应报文
HTTP响应组成:响应行、响应头、响应体。 响应行 (HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为(ok) 响应头 Date:生成响应的日期和时间; Content-Type:指定了MIME类型的HTML(text/html),编码类型是ISO-8859-1 响应体
- GET和POST区别
- GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.
- GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
- GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。
- GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.
websocket
首先Websocket是基于HTTP协议的,或者说借用了HTTP的协议来完成一部分握手。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
-
http long poll 和 ajax 轮询都可以实现实时信息传递
- ajax轮询: 让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。
- long poll 都是采用轮询的方式,不过采取的是阻塞模型,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始
-
特点:
- 解决了http协议只能从客户端向服务器发送请求的缺陷,有了websocket,服务器也能主动向客户端推送消息
- 和http一样,是建立在tcp协议之上,默认端口也是80和443,
- 没有同源限制,客户端可以与任意服务器通信
- 协议标识符是ws,服务器网址就是URL
- 可以发送文本,也可以发送二进制数据
socket.io
socket.io 是一个能实现多人远程实时通信(聊天)的库
它包装的是 H5, WebSocket和轮询, 如果是较新的浏览器内部使用 WebSocket,如果浏览器不支持, 那内部就会使用轮询实现实时通信
网页从输入网址到渲染完成经历了哪些过程
1 输入网址
2 发送到DNS服务器,并获取域名对应的web服务器对应的ip地址
3 与web服务器建立TCP连接
4 浏览器向web服务器发送http请求
5 web服务器响应请求,并返回指定url的数据(或错误信息,或重定向的新的url地址)
6 浏览器下载web服务器返回的数据及解析html源文件
7 生成DOM树,解析css和js,渲染页面,直至显示完成
数据结构和算法
// reduce
function reduce(ary, f, initVal) {
var start = 0
if (arguments.length == 2) {
initVal = ary[0]
start = 1
}
for (var i = start; i < ary.length; i++) {
initVal = f(initVal, ary[i], i, ary)
}
return initVal
}
// flattenDeep
function flattenDeep(ary) {
return [].concat(...ary.map(val => {
if (Array.isArray(val)) {
return flattenDeep(val)
} else {
return val
}
}))
}
ES6 新特性
- 函数默认值
- 模板字符串:
123${a}456
,\ - 解构赋值
- let & const
- let 无变量提升,有块级作用域,禁止重复声明
- const 无变量提升,有块级作用域,禁止重复声明,禁止重复赋值
- 新增库函数
- Number .EPSILON / .isInteger / .isInteger
- String .includes / .repeat / .startsWith / .endsWith
- Array .fill / .findIndex / .of() /
- Object .assign
- Math
- 箭头函数:共享父级 this 对象,共享父级 arguments,不能当做构造函数
- 类 & 继承
- 本质为对原型链的二次包装;类没有提升;不能使用字面量定义属性;动态继承类的构造方法中 super 优先 this
- 模块
- 每个模块都有自己完全独立的代码块,跟作用域类似,但是更加封闭。
- 无限制导出导出
- 内联导出:严格模式下运行使用 export 关键字,后面紧跟声明关键字(let、function 等)声明一个导出对象,声明并同时导出的导出方式
- 对象导出
- 一个模块只能有一个默认导出
ES8 新特性
- String:新增padStart,padEnd
- Object.values 方法返回一个给定对象自己的所有可枚举属性值的数组
- Object.entries 方法返回一个给定对象自身可遍历属性 [key, value] 的数组
- Object.getOwnPropertyDescriptors 方法返回指定对象所有自身属性的描述对象
- 函数参数和函数调用中的尾逗号
- Async 函数
BOM / DOM
- DOM文档对象模型,BOM浏览器对象模型
- DOM 是针对 HTML 和 XML 提供的一个API,为了能以编程的方法操作这个 HTML 的内容。将html中的每个元素都看作是一个对象,每个对象都叫做一个节点,这些节点组成一个DOM树。document是DOM树的根节点
- BOM 是浏览器提供的附加对象,用于处理文档之外的所有内容,比如alert/confirm/prompt,BOM包含的对象有,document,screen,location,history,navigator
- DOM是所有W3C标准都必须遵守的规则,BOM是各浏览器厂商遵守的规则
- BOM的核心是window,它既是通过js访问浏览器窗口的一个接口,又是一个Global(全局)对象。这意味着在网页中定义的任何对象,变量和函数,都以window作为其global对象。
- DOM通过创建树来表示文档,描述了处理网页内容的方法和接口,从而使开发者对文档的内容和结构具有控制力,用DOM API可以轻松地删除、添加和替换节点。
- DOM 的根节点是BOM 的window 对象的子对象。
图片懒加载
- 三个API,我们获得了三个值:
- 可视区高度clientHeight、
- 元素相对于其父元素容器顶部的距离offsetTop、
- 浏览器窗口顶部与容器元素顶部的距离也就是滚动条滚动的高度scrollTop。
- 当offsetTop - scroolTop < clientHeight,则图片进入了可视区内,则被请求。
var imgs = document.querySelectorAll('img');
//offsetTop是元素与offsetParent的距离,循环获取直到页面顶部
function getTop(e) {
var T = e.offsetTop;
while(e = e.offsetParent) {
T += e.offsetTop;
}
return T;
}
function lazyLoad(imgs) {
var H = document.documentElement.clientHeight;//获取可视区域高度
var S = document.documentElement.scrollTop || document.body.scrollTop;
for (var i = 0; i < imgs.length; i++) {
if (H + S > getTop(imgs[i])) {
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
lazyLoad(imgs);
}
原型,闭包,高级函数,异步
- 闭包就是一个函数里面生成并返回一个函数,返回的这个函数能读取到外部函数里面的变量
- 原型就是 a 是实例,b 是构造函数,然后a.proto === b.prototype,使用instanceof来判断的时候就是不停地向上寻找,还有读取a的某个属性如果没有,就会默认去a的原型上找
- 高阶函数:高阶函数是一个接收函数作为参数或将函数作为输出返回的函数 map/reduce/filter
- 异步:js是单线程的,但浏览器是多线程的,当js运行遇到异步代码时,会将代码交给webapi异步执行,js则可以继续执行下面的代码;异步代码会被塞入task queue里排队,task queue会一直观察栈里代码有没有执行完成,一旦发现栈空了,就会调用回调函数,然后重新回到js线程中执行
- https://www.zhihu.com/search?type=content&q=js%E5%BC%82%E6%AD%A5
- async表示该函数要做异步处理。await表示后面的代码是一个异步操作,等待该异步操作完成后再执行后面的动作。如果异步操作有返回的数据,则在左边用一个变量来接收它。
sessionstorage localstorage cookie区别
- 传递方式不同
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。
sessionStorage和loaclStorage不会自动把数据发给服务器,仅在本地保存。 - 数据大小不同
cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
cookie数据最大4k,sessionStorage和localStorage比cookie大得多,可以达到5M或者更大。 - 数据有效期不同
sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
cookie只在设置cookie过期时间之前一直有效,即使窗口或浏览器关闭。 - 作用域不同
sessionStorage不同的浏览器窗口不能共享,即使是同一个页面;
localStorage所有同源窗口都是共享的;
cookie所有同源窗口中都是共享的。
session / cookie
Cookie 可以保持登录信息到用户下次与服务器的会话,换句话说,下次访问同一网站时,用户会发现不必输入用户名和密码就已经登录了(当然,不排除用户手工删除Cookie),Cookie满足同源策略
Cookie 在生成时就会被指定一个Expire值,这就是Cookie的生存周期,在这个周期内Cookie有效,超出周期Cookie就会被清除。有些页面将Cookie的生存周期设置为“0”或负值,这样在关闭浏览器时,就马上清除Cookie,不会记录用户信息,更加安全。由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
event loop
第一步确认宏任务,微任务
宏任务:script,setTimeout,setImmediate,promise中的executor
微任务:promise.then,process.nextTick
process.nextTick优先级高于Promise.then
timers: setTimeout / setInterval
I/O callbacks: 不在其他阶段的所有回调函数
poll: 获取新的I/O事件
check:执行setImmediate
close callback: 执行关闭事件的回调函数
在整个轮询的开始执行process.nextTick
然后再执行setTimeOut、setInterval
再执行其他的回调函数
最后执行setImmediate
发送ajax请求
axios / fetch
Node.js
Node核心思想:1.非阻塞; 2.单线程; 3.事件驱动。
Node 是一个服务器端 JavaScript 解释器
当线程遇到IO操作的时候,不会以阻塞的方式等待IO操作完成或者数据的返回,而是将IO操作发送给操作系统,
然后接着执行下一个操作,当操作系统执行完IO操作之后,以事件的方式通知执行IO的线程,
线程会在特定的时候执行这个事件。这一切的前提条件就是,系统需要一个事件循环,
以不断的去查询有没有未处理的事件,然后给预处理。
Redux
redux 是一个独立的专门用于状态管理的js库
可以管理react应用中多个组件共享的状态
用redux对组件的状态进行集中式管理
组件:两个方面
展现数据 状态显示
与用户交互更新数据 更新状态
redux核心是一个store(仓库)
组件直接从store中读取状态
更新状态:
1. Action Creators ==>> dispatch(action) :传两个值(type和data) type是传的类型(删除,增加,创建,更新)
2. store
3. Reducers ==>> 接受(previousState, action) 返回(newState)
4. React Component
createStore()
store: 管理state, reducer
方法: getState() , dispatch(action) , subscribe(listener)
action对象
reducer返回的是新的状态
applyMiddleware 中间件
thunk 异步
diff算法
- 只在同层进行比较
- 如果节点发生变化,那么就直接替换
- 如果节点相同,递归比较子节点的变化
- 如果有key,那么就会key相同的进行比较
react-redux 的核心就是一个connect函数,接收两个参数,mapStatetoprops,mapdispatchtoprops,返回一个高阶组件,这个高阶组件接受一个组件,返回一个组件,但是这个返回的组件的props上面多了数据以及操作数据的方法
function connect(mapStateToProps,mapDispatchToProps){
return function(com){
return class extends React.Component{
render(){
return (
<Consumer>
{store=>{
state = mapStateToProps(store.getState())
dispatch = mapDispatchToProps(store.dispatch)
return <Comp {...state}{...dispatch}></Comp>
}}
</Consumer>
) }
}
}
}
容器组件和展示组件
- 容器组件负责管理数据和逻辑
- 展示组件负责UI的呈现
- 他们通过react-redux提供的connect方法取得联系
为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。
其中ACK报文是用来应答的,SYN报文是用来同步的。
但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,
所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。
只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
- 三次挥手:
- 客户端发送 SYN 包到服务端,等待服务端确认
- 服务端收到 SYN 包,同时自己也发送一个 SYN+ACK 包给客户端
- 客户端接收到 SYN+ACK 包,向服务端发送确认包 ACK ,发送完毕,客户端与服务端 TCP 连接成功,完成三次握手
- 四次挥手:
- 客户端连续发送释放报文 FIN ,等待服务端确认
- 服务端收到释放报文 FIN ,发出确认报文 ACK
redux
action: 是store唯一的信息来源,把action发送给store必须通过store的dispatch方法。
每个action必须有一个type属性描述action的类型。
XSS 与 CSRF 两种跨站攻击
- xss 跨站脚本攻击,主要是前端层面的,用户在输入层面插入攻击脚本,改变页面的显示,或则窃取网站 cookie,预防方法:不相信用户的所有操作,对用户输入进行一个转义,不允许 js 对 cookie 的读写
- csrf 跨站请求伪造,以你的名义,发送恶意请求,通过 cookie 加参数等形式过滤
- 我们没法彻底杜绝攻击,只能提高攻击门槛
负载均衡
当系统面临大量用户访问,负载过高的时候,通常会使用增加服务器数量来进行横向扩展,使用集群和负载均衡提高整个系统的处理能力
JS实现继承的方法
1. 原型链继承
将父类的实例作为子类的原型
function Cat() {}
Cat.prototype = new Animal()
Cat.prototype.name = 'cat'
var cat = new Cat()
2. 构造继承
使用父类的构造函数来增强子类的实例,等于是复制父类的实例属性给子类
function Cat(name) {
Animal.call(this)
instance.name = name || 'Tom'
}
var cat = new Cat()
3. 实例继承
为父类实例添加新特性,作为子类的实例返回
function Cat(name) {
var instance = new Animal()
instance.name = name || 'Tom'
return instance
}
var cat = new Cat()