HTML部分
HTML5
1、html语义化:section、nav...
2、本地储存
3、多媒体:video、audio
HTML语义化
- 语义化的含义是用正确的标签做正确的事情,让页面结构符合内容结构,便于浏览器、搜索引擎解析;
- 在没有css样式的情况下,也能以一种文档格式显示,便于阅读;
- 方便搜索引擎的爬虫依赖标签来确定上下文和关键字的权重,利于seo;
- 方便开发者阅读、理解和维护。
localStorage、sessionStorage、cookies、indexDB 的区别
localStorage:没有过期时间,大小为10Mb左右,受同源策略限制,可以用于跨页面数据交互、session;
sessionStorage:与localStorage类似,区别在于关闭浏览器会消失;
indexDB:可储存的数据较多,且采用对象来保存数据;
cookies:
1. 服务器发送给浏览器,并保存在浏览器的一块数据,会在下一次请求是带上;
2. 受同源策略限制;
3. 可以设置过期时间 Expires 或有效期 Max-Age;
4. 可以设置路径 Path;
5. 大小为 4KB;
FormData 表单对象
- 可以用键值对({key:value})来模拟一系列表单控件;
- 跟普通ajax相比, FormData最大的优点就是可以异步上传一个二进制文件;
var data = new FormData(formElement)
data.append("name", "bill")
data.append("userfile", fileInputElement.files[0])
xhr.send(data)
File API 预览图片使用
- File 对象一般来自于input元素上,选择文件之后返回的FileList对象
- 也可以是自由拖放操作生成的DataTransfer对象
- 或者是来自HTMLCanvasElement mozGetAsFile() 方法
- File对象是特殊类型的Blob,可以在 XMLHttpRequest.send()中处理
File.lastModified // 最后修改时间
File.lastModifiedDate // 最后修改时间的 Date 对象
File.name // File 引用文件的名字
File.size // 文件大小
File.path // path 或者 Url
File.type // 文件扩展类型
CSS部分
px、rem、em 的区别
- px:px 是像素,绝对单位。像素px是相对于显示器屏幕分辨率而言的,是一个虚拟长度单位,是计算机系统的数字化图像长度单位,如果px要换算成物理长度,需要指定精确dpi;
- rem:rem 是CSS3新增的一个相对单位(root em,根em),使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素;
- em:em是相对长度单位,相对于当前对象内文本的字体尺寸。如果未对当前行内文本的字体尺寸进行设置,则相对于浏览器的默认字体尺寸。它会继承父级元素的字体大小,因此并不是一个固定的值。
position
- static:默认值;
- relative:相对原来应该出现的位置;
- absolute:相对 position 值不为 static 的祖先元素的位置;
- fixed:相对整个窗口的位置;
- sticky:粘性定位。
Javascript
值类型与引用类型
- 值类型:undefined、null、boolean、number、string、symbol
基本类型的数据保存在栈内存上 - 引用类型:object、array、function
引用类型在堆栈中保存了变量标识符和指向该对象的指针
数据实际保存在堆内存中
// 判断基本类型
typeof a
// 判断引用类型
Array.isArray(a)
Object.prototype.toString.call(a)
call、apply、bind 的区别
- call:第一个参数是函数里面的 this,第 2, 3, 4, 5, ... 个参数会依次作为参数传给函数;
- apply:第一个参数是函数里面的 this,第 2 个参数是要传给函数的参数列表;
- bind:第一个参数是函数里面的 this,返回一个指定了 this 的函数;bind 还可以接受额外的参数,之后的一序列参数将会在传递的实参前传入作为它的参数。
var log = console.log.bind(console, "test");
var log = console.log.call(console, arg1, arg2)
var log = console.log.apply(console, [arg1, arg2])
log("hey") // test hey
原型链
- JS没有类的概念,实现继承的时候,需要通过原型链。
- 每个对象都有一个[[proto]]属性,指向的是其原型对象,原型对象也有属于自己的原型对象,最后会指向 null
- 获取一个属性或调用一个方法的时候,先在对象本身找,找不到的时候就在其原型对象上找,如果再找不到就再往原型的原型找,直至找到或直到最后找不到。
// 组合继承(常用)
// 用 构造函数 来出现实例属性的继承
// 用 原型 来实现原型属性和函数的继承
var SuperType = function (name) {
this.name = name
this.colors = ["red", "yellow"]
}
SuperType.prototype.sayName = function () {
alert(this.name)
}
var Subtype = function (name, age) {
// 通过工厂函数来继承 属性
SuperType.call(this, name)
this.age = age
}
// 通过原型的实例来继承 方法
Subtype.prototype = new SuperType()
Subtype.prototype.constructor = Subtype
Subtype.prototype.sayAge = function () {
alert(this.age)
}
// 寄生组合式继承(最佳实践)
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var inheritPrototype = function (subType, superType) {
// 继承 超类型的原型 的属性
var prototype = object(superType.prototype)
prototype.constructor = subType
subType.prototype = prototype
}
var SuperType = function (name) {
this.name = name
this.colors = ["red", "yellow"]
}
// 超类型的原型只有 方法
SuperType.prototype.sayName = function () {
alert(this.name)
}
var Subtype = function (name, age) {
// 先获取一份属于自己的 超类型 的属性
SuperType.call(this, name)
this.age = age
}
inheritPrototype(Subtype, SuperType)
Subtype.prototype.sayAge = function () {
alert(this.age)
}
var a = new Subtype("bill")
事件捕获、事件冒泡、事件委托
- 事件捕获=>事件触发=>事件冒泡
- addEventListener(event, callback, useCapture),useCapture默认为 false,如果为 true,将会在捕获阶段去触发事件
- event.stopPropagation(),可阻止事件继续传播(阻止冒泡)
- 事件委托: 利用冒泡原理,在父元素或者祖先元素上绑定事件监听函数
闭包
- 被作用域封闭的变量,常见的用法可以一用于实现单例
const configuredEnvironment = (() => {
let env = null
const f = () => {
if (env === null) {
// 得到用于加载模板的目录
const p = path.join(__dirname, 'templates')
// nunjucks 会从这个目录中读取模板, 调用 render 方法加载模板并且返回
env = nunjucks.configure(p)
return env
} else {
return env
}
}
return f
})()
深拷贝
var deepClone = function(x) {
var newX
if (Array.isArray(x)) {
newX = []
for (var i = 0; i < x.length; i++) {
var item = deepClone(x[i])
newX.push(item)
}
} else if (typeof(x) === "object") {
newX = {}
for (var i in x) {
var item = deepClone(x[i])
newX[i] = item
}
} else {
newX = x
}
return newX
}
var arr = [[1,2,3],{a:1,b:2},55]
var newArr = deepClone(arr)
var deepCloneFromJson = function(a) {
var x = JSON.stringify(a)
var b = JSON.parse(x)
return b
}
AJAX
var ajax = function(method, path, data, responseCallback) {
var r = new XMLHttpRequest()
// 设置请求方法和请求地址
r.open(method, path, true)
// 设置发送的数据的格式
r.setRequestHeader('Content-Type', 'application/json')
// 注册响应函数
r.onreadystatechange = function() {
if(r.readyState === 4) {
responseCallback(r)
}
}
// 发送请求
r.send(data)
}
// 0 代理被创建,但并未 open()
// 1 已经调用 open()
// 2 已经调用 send() 并且头部和状态已经获得了
// 3 正在传输
// 4 传输完成
HTTP
- 定义:网络中,数据传输双方遵守的协议,因为收发的是文本格式的数据,所以叫超文本传输协议。
- 格式:
1,请求行或者响应行(GET /api/subject/19 HTTP/1.1; HTTP/1.1 200 OK)
2,Header 字段(请求的 Header 中 Host 字段是必须的,其他都是可选)
3,\r\n\r\n(连续两个换行回车符,用来分隔 Header 和 Body)
4,Body(可选) - 协议中标识了传输的协议版本、域名、路径、方法以及cookie、connection等其他头部字段,接收的一方会解析协议内容,然后更具不同的条件来做出不同的处理以及响应。
- 状态码:
1** 服务器收到请求,需要请求者进一步的操作;
2** 成功,操作被接受并处理;
3** 重定向,需要进一步的操作;
4** 客户端错误,可能存在语法错误或无法完成的请求;
5** 服务器错误,服务器在处理请求过程中发生了错误。
缓存机制
一般将缓存保存在代理服务器或客户端本地
- 原理:
- 初次请求:
浏览器向服务器发送请求,服务器返回响应资源,以及缓存规则,资源及缓存规则会在缓存数据库保存一份副本
- 再次请求:
浏览器会带上相关的信息向服务器发送请求,服务器根据附带的信息判断缓存是否过期,
如果过期,则从服务器返回相应的资源缓存规则,
如果缓存有效,则从缓存数据库返回资源 - 具体例子:
- 强制缓存:
response
Cache-Control:max-age=31536000
Expires:Fri, 30 Oct 1998 14:19:41(http 1.0 的字段,现在基本可以忽略
之后所有的请求,只要在365天之内的请求,都从缓存里面返回
- 对比缓存:
Last-Modified/If-Modified-Since
response
Last-Modified:Thu, 03 Jul 2012 00:00:00 GMT
request
If-Modified-Since: Thu, 03 Jul 2012 00:00:00 GMT
请求的时候会对比修改的时间,判断请求的资源最后修改时间是否一致,如果一致,则从缓存里获取
Etag/If-None-Match
response
Etag:“xxxxx”
request
If-None-Match: “xxxxx”
请求的时候会对比请求资源的标记信息是否一致,如果一致,则从缓存里获取
该组合的判断权重比 Last-Modified/If-Modified-Since 高
HTTPS
- http有以下几个问题:
1、通讯是明文的,所有人都有可能看到
2、不验证通讯方的身份,有可能遭遇伪装
3、无法证明报文的完整性,有可能接收到纂改过的报文 - https
1、实际上是在http的基础上加了一层安全通道(ssl,Secure Socket Layer,安全套接层/ tsl,Transport Layer Security,安全层传输协议)
2、同时使用了证书的手段,帮助验明通讯双方的身份 - 证书体系
1、服务器把自己的服务器公钥登陆至认证机构
2、认证机构用自己的证书私钥向服务器公钥签名颁发数字证书
3、一般情况下,浏览器会预先植入证书公钥
开始通讯的时候:
4、服务器把服务器公钥和数字证书发给浏览器
5、浏览器通过认证机构确认服务器公钥的真实性
6、确认过后,浏览器用服务器公钥加密报文发给服务器
7、服务器收到报文,用服务器私钥解密
在顺利发送了服务器公钥后:
8、服务器向浏览器发送对称密钥
9、浏览器拿到对称密钥,以对称加密的方式传输数据
跨域
- jsonp:只能用get方法来获取
- cors:设置被跨域服务器
- 服务器转发请求:node 或 ngnix
网络安全
- xss
原因:在页面中添加非法 JS 代码,可能会删除用户的信息或获取用户的cookie
防范:在对用户的输入进行转译 - xsrf
原因:伪造用户的请求去访问接口
防范:请求时使用一次性token,setCookie设置HTTP only
重绘、重排
- 重排:页面布局改变会引起重排,重排的同时会重绘
- 重绘:颜色、图案等变化会引起重绘
前端优化
- 内容
- 减少 http 请求次数
- 减少 DNS 查询
- 减少重定向次数
- ajax 可以缓存 Expires Cache Control Header 头
- 首屏以外的组件延迟加载
- 猜测用户的使用倾向,预加载
- 减少 html 的 dom 数量
- 跨域分离组件, 可以多服务器并行
- 杜绝 404
- 少用 iframe
- CSS:
- 样式表放在顶部
- 引入 css 时使用 link 不用 import
- 避免使用滤镜
- JS :
- script 放在最后
- 少操作 dom,避免重绘
- 去除重复的 script
- 多用事件委托
- 图片:
- 压缩图片
- 使用雪碧图 / base64
- 不用 html css 设置图片的大小,而尽量使用原图的大小
- cookie:
- 给 cookie 减肥
- 把静态资源放在与 cookie 无关的域名下
输入url到渲染页面
一、浏览器查找域名对应的 IP 地址;
- DNS查询:浏览器缓存》系统缓存》路由器缓存》IPS服务器缓存》根域名服务器缓存》顶级域名服务器缓存》主域名服务器缓存
- DNS负载均衡:通常由多台服务器来分别处理来自四面八方的请求,DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡,又叫做DNS重定向
二、浏览器根据 IP 地址与服务器建立 socket 连接;
- 三次握手
- http 和 https
三、浏览器与服务器通信:浏览器请求,服务器处理请求;
四、浏览器渲染页面;
- 解析HTML文件构建DOM树
- 解析CSS文件
- 合并成渲染树
- 布局渲染树并将其绘制到屏幕上
- 浏览器在解析过程中,如果遇到请求外部资源时,如图像、iconfont等,浏览器将异步下载该资源,不会堵塞页面渲染
- 遇到JS文件,HTML文档会挂起渲染过程,因为JS有可能修改DOM结构
五、浏览器与服务器断开连接。
- 四次挥手
react.js
- 为什么要使用react?
状态:通过state来管理web应用的状态,通过状态的改变来推导出新的ui
组织:组件化,模块化,代码组织得比较好
效率:采用虚拟dom,diff算法,相比直接操作dom,性能要更加好 - 虚拟dom
用js构建一颗虚拟的dom树,改动的时候,先对虚拟的dom树进行改动
然后用diff算法对改动前后的虚拟树进行对比,再去更新浏览器的dom
好处是:批处理 - diff算法
实际上是计算最少操作数
在进行比较的时候,一旦发现不是同一类型的节点,会直接替换,不会进行后续比较
对于同一类型的节点,会对其属性进行重设,实现节点的转换 - state
state的改变会影响ui的改变,只能通过setState来进行改变 - props
同样影响组件的行为和表现,但一旦设置,就不能改变 - 生命周期
- 挂载:
componentWillMount()
componentDidMount()
- 更新:
componentWillReceiveProps(newProps)
shouldComponentUpdate(newProps, newState)
componentWillUpdate(nextProps, nextState)
componentDidUpdate(prevProps, prevState)
- 卸载:
componentWillUnmount() - 父子组件通讯
将改变父组件state的函数,作为props传递给子组件去使用 - redux
1、store 保存数据的地方
2、state 包含所有数据,如果有拿到数据,需要使用 store.getState()
3、action 用户是触摸不了 state 的,要通过 action.dispatch() 来发出通知给 store
4、reducer 在收到 action 后,必须通过计算返回一新的 state,这个计算过程就通过 reducer 函数来进行