前言:希望可以通过这篇文章,能够给你得到帮助。(感谢一键三连),前端小白不断升级打怪中...
HTML
1. 如果理解HTML语义化?
语义化以便于代码可阅读性(让人更容易读懂代码) 搜索引擎,容易分别网页主次关系SEO(让搜索引擎更容易读懂)
2. 默认情况下,哪些HTML标签是块级元素,哪些是内联元素?
- display:block/table;有div h1 table ul ol p等
- display:inline/inline-block; 有span img input button等
CSS
布局
1. 盒子模型
#div {
width: 100px
padding: 10px
margin: 10px
border: 1px solid $ccc
}
offsetwidth = (内容宽度+内边距+边框),无外边框
默认是: box-sizing: content-box;
122
设置
box-sizing:border-box
100
2. margin纵向重叠的问题
p {
margin-top: 10px;
margin-bottom: 15px;
}
<p>AAA</p>
<p></p>
<p></p>
<p></p>
<p>BBB></p>
相邻元素的margin-top和margin-bottom会发生重叠 空白内容的
也会重叠 答案:15px3. margin负值的问题
- margin-top/margin-left 元素向上,向左移动
- margin-right负值,右侧元素左移,自身不受影响
- margin-bottom,下侧元素上移,自身不受影响
4. BFC理解和应用
BFC块级格式化上下文
形成BFC的常见条件:
- float不是none
- position是absulute或fixed
- overflow不是visible
- dispaly是flex inline-block等
BFC常见应用: 清除浮动
5. float布局的问题,以及clearfix
如何实现圣杯布局和双飞翼布局?
目的:
三栏布局,中间一栏最先加载和渲染(内容最重要) 两侧内容固定,中间内容随着宽度自适应 一般用于PC网页
技术总结:
使用float布局 两侧使用margin负值,以便和中间内容横向重叠 防止中间内容被两侧覆盖,一个用padding一个用margin
圣杯布局: padding
双飞翼布局: margin
手写clearfix?
.clearfix:after{
content: '';
display: table;
clear: both
}
.clearfix {
*zoom: 1; /*兼容IE低版本 */
}
6. flex画色子
flex实现一个三点的色子?
flex-direction
justify-content // 主轴对齐方式
align-items
flex-wrap // 是否换行
align-self // 交叉轴
定位
absolute relative
7. absolute和relative分别依据什么定位?
- relative 依据自身定位
- absolute依据最近一层的定位元素 absolute relative fixed
8. 居中对齐有哪些实现方式?
- 水平居中 inline元素: text-align: center
block元素: margin: auto
absolute元素: left: 50% + margin-left负值
- 垂直居中
inline元素:line-height的值等于height值
absolute元素:top: 50% + margin-top负值 前提:知道子元素的高度,宽度
absolute元素: transform:translate(-50%, -50%) 兼容性问题
absolute元素: top, left,bottom, right = 0 + margin: auto
9. line-height的继承问题
写具体数值,如30px,则继承该值
写比例,如2/1.5,则继承该比例 p的font-size*1.5 = 24px
写百分比,如200%,则继承计算出来的值 font-size * line-height百分比 20* 200% = 40px
body {
font-size: 20px
line-height: 200%
}
p{
font-zise: 16px
}
p标签的line-height 20*200% = 40px
图文样式
响应式
10. rem是什么?
rem是一个长度单位
px:绝对长度单位,最常用
em:相对长度单位,相对于父元素,不常用
rem:相对长度单位,相对于根元素,常用于响应式布局
html{
font-size:100px
}
div {
font-size: 0.16rem
}
响应式布局的常见方案? media-query,根据不同的屏幕宽度设置根元素的font-size rem,基于根元素的相对单位
iphone5或者更小的尺寸 max-width:374px ---- html { font-size: 86px }
iphone6/7/8 和iphone x min-width: 374px and max-width:413px ----html { font-size: 100px }
iphone6p或者更大的尺寸 min-width: 414px ----html { font-size:110px }
body { font-size: 0.16rem; }
rem的弊端:阶梯型
网页视口尺寸
window.screen.height // 屏幕高度
window.innerHeight // 网页视口高度 去头去尾
document.body.clientHeight // body高度
vw/vh
vw 网页视口宽度的1/100
vh 网页视口高度的1/100
vmax取两者最大值;vmin取两者最小值 --- 横屏时
JS
1. typeof能判断哪些类型
识别所有值类型
识别函数 function
判断是否引用类型(不可再细分)Object
2. == ===
3. 值类型和引用类型的区别
值类型: Number String Boolean undefined Symbol
引用类型:null 数组 对象 函数
4. 写手深拷贝
变量类型 引用类型 typeof运算符
深拷贝
5. 类型转换
字符串拼接
==
if语句和逻辑判断
falsely变量
!!0 === false
!!NAN === false
!!null === false
!!undefined === false
!!false === false
6. 原型和原型链
7. class和继承
constructor
属性
方法
extends继承
super父类
扩展 重写
8. 类型判断instanceof
判断引用类型
Object 是所有引用类型的父类
[] instanceof Array // true
[] instanceof Object // true
{} instanceof Object // true
9. 原型
class实际是function实现的
proto
prototype
先在自身寻找属性和方法
找不到则自动去__proto__中寻找
10. 原型链
11. 作用域和闭包
this的不同场景,如何取值?
手写bind函数
实际开发中闭包应用场景?
作用域和自由变量
全局作用域,函数作用域,块级作用域
自由变量:
定义:
- 一个变量在当前作用域没有被定义,但被使用了
- 向上级作用域,一层一层依次寻找,直到找到为止
- 如果到全局作用域都没找到,则报错xx is not defined
闭包:
作用域应用的特殊情况,有两种表现:
函数作为参数被传递
函数作为返回值被返回
函数作为返回值被返回
function create() {
const a = 100
return function() {
console.log(a)
}
}
const fn = create()
const a = 200
fn() // 100
函数作为参数被传递
// 闭包:自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方
function print(fn) {
const a = 200
fn()
}
const a = 100
function fn() {
console.log(a)
}
print(fn) // 100
this:
作为普通函数
使用call apply bind
作为对象方法被调用
在class方法中调用
箭头函数 // 箭头函数的this是取上级作用域的值
this取什么值,是在函数执行的时候决定的,不是在定义的时候决定的
bind:
Function.prototype.bind2 = function() {
const args = Array.prototype.slice.call(arguments)
const t = args.shift() // 数组第一项 args 剩余参数
const self = this
return function() {
return self.apply(t, args)
}
}
function fn(a, b) {
console.log(this)
console.log(a, b)
}
const fn2 = fn.bind2({ a: 2} , 2, 3 )
fn2() // { a: 2 } 2 3
闭包应用:
隐藏数据
12. 单线程和异步
同步和异步的区别是什么?
基于JS是单线程语言
异步不会阻塞代码执行
同步会阻塞代码执行
手写Promise加载一张图片
前端使用异步的场景有哪些?
单线程和异步
应用场景
callback hell和promise
JS是单线程语言,只能同时做一件事
浏览器和nodejs已支持JS启动进程,如Web Worker
JS和DOM渲染共用同一个线程,因为JS可修改DOM结构
遇到等待(网络请求,定时任务)
需要异步
回调callback函数形式
应用场景:
网络请求,如ajax图片加载
定时任务,如setTimeout
手写Promise加载一张图片
Promise 解决callback hell问题
function loadImg(src) {
return new Promise((resolve, reject) => {
const img = document.createElement('img')
img.onload = ()=>{
resolve(img)
}
img.onerror = () => {
reject(new Error())
}
img.src = src
})
}
const url= ''
const url2 = ''
loadImg(url).then(img=> {
console.log(img.width)
return img
}).then( img => {
console.log(img.height)
return loadImg(url2)
}).then(img2 =>{
}).catch(err =>{
})
13. 异步-进阶
event loop
请描述event loop(事件循环/事件轮询)的机制?
什么是宏任务和微任务,两者有什么区别?
Promise有哪三种状态?如何变化?
async/ await 语法
promise和setTimeout执行顺序?
外加async/await的顺序问题?
14. event loop(事件循环/事件轮询)
JS是单线程运行的
异步要基于回调来实现
event loop就是异步回调的实现原理
JS如何执行?
从前到后,一行一行执行
如果某一行执行报错,则停止下面代码
先把同步代码执行完,再执行异步
Event Loop过程:
同步代码,一行一行放在Call Stack执行
遇到异步,会先‘记录’下,等待时机(定时,网络请求等)
时机到,就移到Callback Queue
如Call Stack为空(即同步代码执行完)Event Loop开始工作
轮询查找Callback Queue, 如有则移到到Call Stack执行
然后继续轮询查找(永动机一样)
- Call Stack:代码执行
- Web ApIs:处理定时器,异步API
- Callback Queue:放置待执行的定时器/网络请求返回结果
- Event Loop 循环,从Callback Queue队列轮询,--》 进入Call Stack 执行
15. DOM事件和event loop
JS是单线程
异步(色图Timeout,ajax等)使用回调,基于event loop
DOM事件也使用回调,基于event loop,但DOM事件不是异步的
16. promise
三种状态
状态的表现和变化
then和catch对状态的影响
三种状态:
pending resolved rejected
pending-》resolved或者rejected
状态是不可逆的
pending状态,不会触发then和catch
resolved状态,会触发then
rejected状态,会触发catch
then和catch改变状态
then正常返回resolved,里面有报错则返回rejected
catch正常返回resolved,里面有报错则返回rejected
Promise.resolve().then(() =>{
console.log(1)
}).catch(() =>{
console.log(2)
}).then(() => {
console.log(3)
})
// 1
// 3
Promise.resolve().then(() =>{
console.log(1)
throw new error('err');
}).catch(() =>{
console.log(2)
}).then(() => {
console.log(3)
})
// 1
// 2
// 3
Promise.resolve().then(() =>{
console.log(1)
throw new error('err');
}).catch(() =>{
console.log(2)
}).catch(() =>{
console.log(3)
})
// 1
// 2
```
```javascript
Promise.reject().then(() =>{
console.log(1)
}).catch(() =>{
console.log(2)
}).then(() => {
console.log(3)
})
// 2
// 3
Promise.reject().then(() =>{
console.log(1)
throw new error('err');
}).catch(() =>{
console.log(2)
}).then(() => {
console.log(3)
})
// 2
// 3
Promise.reject().then(() =>{
console.log(1)
throw new error('err');
}).catch(() =>{
console.log(2)
}).catch(() =>{
console.log(3)
})
// 2
(async function() {
console.log('start')
const a = await 100;
console.log('a', a);
const b = await Promise.resolve(200)
console.log('b', b)
const c = await Promise.reject(300) // 报错后面不执行
console.log('c', c)
console.log('end')
})()
// start
// a 100
// b 200
17. async/await
异步回调 callback hell
promise then catch链式调用,但也是基于回调函数
async/await 是同步语法编写异步代码,彻底消灭回调函数
18. async/await和Promise的关系
async/await是消灭异地回调的终极武器
但和Promise并不互斥,反而,两者相辅相成
执行async函数,返回的是Promise
await相对于Promise的then
try...catch可捕获异常,代替了Promise的catch
async function fn() {
return 100
}
(async function() {
const a = fn()
const b = await fn()
console.log(a)
console.log(b)
})()
// Promise { 100 }
// 100
19. 异步的本质
async/await是消灭异步回调的终极武器
JS还是单线程,还得是有异步,还得是基于event loop
async/await只是一个语法糖,但这个糖真香!
async function async1() {
console.log('async1 start') // 2
await async2()
// await 后面,都可以看成callback里的内容,即异步
// 类似event loop ,setTimeout()
// setTimeout(function() { console.log('async1 end')})
// Promise.then(res => {console.log('async2 end')})
console.log('async1 end') // 5
}
async function async2() {
console.log('async2') // 3
}
console.log('start') // 1
async1()
console.log('end') // 4
打印:
start
async1 start
async2
end
async1 end
async function async1() {
console.log('async1 start') // 2
await async2()
// await 后面,下面三行都可以看成callback里的内容,即异步
console.log('async1 end') // 5
await async3()
// await,下面一行看成callback里的内容
console.log('async1 end2') // 7
}
async function async2() {
console.log('async2') // 3
}
async function async3() {
console.log('async3') // 6
}
console.log('start') // 1
async1()
console.log('end') // 4
打印:
start
async1 start
async2
end
async1 end
async3
async1 end2
20. for...of的使用
for... in(以及forEach for)是常规的同步遍历
for...of常用于异步的遍历
function muti(num) {
return new Promise(resolve =>{
setTimeout(() =>{
resolve(num*num)
}, 1000)
})
}
const nums = [1, 2, 3]
nums.forEach(async (i) =>{
const res = await muti(i)
console.log(res)
})
一秒钟同时打印 1 4 9
forEach同步执行muti,一秒钟后打印
function muti(num) {
return new Promise(resolve =>{
setTimeout(() =>{
resolve(num*num)
}, 1000)
})
}
const nums = [1, 2, 3]
// nums.forEach(async (i) =>{
// const res = await muti(i)
// console.log(res)
// })
!(async function() {
for(let i of nums) {
const res = await muti(i)
console.log(res)
}
})()
// 1 4 9
// for of 先执行完再执行下一个
21. 宏任务macroTask和微任务microTask
什么是宏任务,什么是微任务
event loop和DOM渲染
微任务和宏任务的区别
-
宏任务:setTimeout,setInterval,Ajax, DOM事件
-
微任务: Promise async/await
微任务执行时机比宏任务要早
console.log(100)
setTimeout(() =>{
console.log(200)
})
Promise.resolve().then(res =>{
console.log(300)
})
console.log(400)
// 100 400 300 200
event loop和DOM渲染
JS是单线程的,而且和DOM渲染共用一个线程
JS执行的时候,得留一些时机供DOM渲染
每次Call Stack清空(即每次轮询结果),即同步任务执行完
都是DOM重新渲染的机会,DOM结构如有改变则重新渲染
然后再去触发下一次Event Loop
宏任务:DOM渲染后触发,如setTimout
微任务:DOM渲染前触发,如Promise
<div id="content"></div>
<script>
let p = document.createElement('p');
p.innerHTML = '我是p标签';
document.getElementById('content').append(p);
// 宏任务:DOM渲染之后
setTimeout(() =>{
console.log('length', document.getElementById('content').children.length); // 1
alert('setTimeout'); // DOM渲染了吗--yes
})
// 微任务:DOM渲染之前
Promise.resolve().then(() =>{
console.log('length', document.getElementById('content').children.length); // 1
alert('Promise then'); // DOM渲染了吗? ---No
})
</script>
为什么微任务执行更早
微任务是ES6语法规定的
宏任务是由浏览器规定的
micro task queue 微任务队列
callback queue 宏任务队列
async function async1() {
console.log('async1 start') // 2
await async2()
// await 后面作为回调内容 --微任务
console.log('async2 end') // 6
}
async function async2() {
console.log('async2') // 3
}
console.log('script start') // 1
setTimeout(() =>{ // 宏任务 setTimeout
console.log('setTimeout') // 8
}, 0)
async1()
// 初始化promise时,传入的函数会被立刻执行
new Promise(function(resolve){
console.log('promise1') // 4
resolve()
}).then(function() { // 微任务
console.log('promise2') // 7
})
console.log('script end') // 5
// 1-5 同步代码执行完毕(event loop --call stack 被清空)
// 执行微任务
// 尝试触发DOM渲染
// 触发event loop , 执行宏任务
22. 描述event loop机制(可画图)
23. 从JS基础知识到JS Web Api
JS基础知识,规定语法(ECMA 261标准)
JS Web API,网页操作的API(WC标准)-- 添加DOM元素,文字,设置css样式,监听事件,获取浏览器信息
前者是后者的基础,两者结合才能真正实际应用
JS基础知识:
变量的类型和计算
原型和原型链
作用域和闭包
JS Web API:
DOM操作
BOM操作 浏览器上的操作
事件绑定
ajax
存储
24. 存储:
cookie
localStorage
sessionStorage
cookie:
本身用于浏览器和server通讯
被借用到本地存储来
可用document.cookie = ''来修改
缺点:
存储大小,最大4kb
http请求时需要发送到服务端,增加请求数据量
只能用document.cookie=''来存储
localStorage和sessionStorage:
html5专门为存储而设计,最大可存5M
api简单用setTtem,getItem
不会随着http请求被发送出去
localStorage:
数据会永久存储,除非代码或代码删除
sessionStorage:
数据只操作当前会话,浏览器关闭则请求
一般用localStorage会更多一些
25. DOM
vue和react框架应用广泛,封装了DOM操作
但DOM操作一直都会前端工程师的基础,必备知识
只会vue而不懂DOM操作的前端程序员,不会长久
DOM是哪种数据结构
DOM操作的常用API
attr和property的区别
一次性插入多个DOM节点,考虑性能
DOM本质
DOM节点操作
DOM结构操作
DOM性能
26. DOM本质
树形结构
27. DOM节点操作
获取DOM节点
attribute
property: 修改对象属性,不会体现到html结构中
attribute:修改html属性,会改变html结构中
两者都有可能引起DOM重新渲染
const div = document.getElementById('content')
// property
div.style.color = ''
// attribute
div.getAttribute('index')
div.setAttribute('index', '1')
新增/插入节点
获取子元素列表,获取父元素
删除子元素
const div = document.getElementById('content')
const div2 = document.getElementById('content2')
const p = document.createElement('p')
// 插入标签
div.appendChild(p)
// 移动标签
div2.appendChild(p) // div下p移动动到div2
// 获取父节点
p.parentNode
// 获取子元素
div2.childNodes // 包括文本节点需要筛出掉
div2.childNodes
Array.prototype.slice.call(div2.childNodes).filter(child =>{
return child.nodeType === 1 // 标签节点
// nodeType === 3 // 文本节点
})
28. DOM性能
DOM操作非常‘昂贵’,避免频繁操作DOM
对DOM查询做缓存
将频繁操作改为一次性操作
// 不缓存DOM查询结果
for (let i = 0; i < document.getElementsByTagName('p').length; i++){
// 每次循环,都会计算length,频繁进行DOM查询
}
// 缓存DOM查询结果
const pList = document.getElementsByTagName('p');
const length = pList.length
for( let i =0; i < length;i++){
// 缓存length,只进行一次DOM查询
}
// 频繁操作改成一次性操作
const listNode = document.getElementById('list')
// 创建一个文档片段,此时还没有插入到DOM树中
const frag = document.createDocumentFragment()
// 执行插入
for(let x = 0;x<10;x++){
const li = document.createElement('li');
li.innerHTML = 'list item' + x;
frag.appendChild(li)
}
listNode.appendChild(frag)
29. BOM操作
识别浏览器类型
navigator
screen
location
history
const ua = navigator.useAgent
ua.indexOf('Chrome')
screen.width
loaction.href //网址
loaction.protocal // 协议
loaction.host // 端口号
location.hostname //
loaction.search
loaction.hash
loaction.pathname
history.back()
hitory.forward()
30. 事件
事件绑定
事件冒泡
事件代理
// 事件绑定
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const a = document.getElementById('a')
bindEvent(a, 'click', e => {
e.preventDefault() // 阻止默认行为
alert('clicked')
})
// 事件冒泡
// 事件绑定
function bindEvent(elem, type, fn) {
elem.addEventListener(type, fn)
}
const a = document.getElementById('a')
bindEvent(a, 'click', e => {
e.stopProgation() // 阻止默认行为
alert('clicked')
})
事件冒泡的原理:
基于DOM树形结构
事件会顺着触发元素往上冒泡
应用场景:代理
// 事件代理
// 事件绑定在父级标签,默认行为
const btn = document.getElementById('btn')
bindEvent(btn, 'click','a', function(event) {
event.preventDefault()
alert(this.innerHTML)
})
function bindEvent(elem, type,selector, fn) {
if (fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, event =>{
const target = event.target
if (selector) {
// 代理绑定
if (target.matchs(selector)) {
fn.call(target, event)
}
} else {
// 普通绑定
fn.call(target, event)
}
})
}
31. http
http常见状态码
http常见headers
Resrful API
http缓存机制
http状态码
1xx 服务器收到请求
2xx请求成功, 如200
3xx重定向, 如302
4xx客户端错误, 如404
5xx服务端错误,如500
301永久重定向,浏览器是永久的老地址不用了,直接访问返回的重定向地址
302临时重定向, 浏览器还是访问老地址
304资源未被修改
403没有权限
504网关超时
methods
get 获取数据
post 新建数据
patch/put 更新数据
delete 删除数据
Restful API
传统API设计: 把每个url当做一个功能
Restful API设计:把每个url当做一个唯一的资源
尽量不用url参数
用method表示操作类型
传统API设计:/api/list?pageIndex = 2
Restful API设计:/api/list/2
http常见headers
request headers
Accept 浏览器可接收的数据格式
Accept-Encoding浏览器可接收的压缩算法
Accept_Languange浏览器可接收的语言,如zh-CN
Connection: keep-alive一次TCP连续重复使用
cookie:同域浏览器自动携带
Host:域名
User-Agent(UA)浏览器信息
Content-type发送数据的格式:如application/json
response headers:
Content-type: 返回数据的格式
Content-length:返回数据的大小
Content-encoding:返回数据的压缩算法:肉gzip
Set-Cookie:设置cookie
header自定义header
缓存相关的header
Cache-Control Expires
Last-Modified IF-Modified-Since
Etag If-None_match
32. http缓存
http缓存策略(强制缓存+协商缓存)
什么是缓存?
为什么需要缓存?
哪些资源可以被缓存?-静态资源(js css img)
http缓存:强制缓存
Cache-Control
在Response Headers中
控制强制缓存的逻辑
例如Cache-Control: max-age = 31536000(单位是秒)
cache-control的值:
max-age
no-cache
no-store
private
public
Expires
同在Responese Headers
同为控制缓存过期
已被Cache-Control代替
http缓存-协商缓存
服务器端缓存策略
服务器判断客户端资源,是否贺服务器资源一样
一致则返回304,否则返回200和最新的资源
资源标识
在Response Headers中,有两种:
Last-Modified资源的最后修改时间
Etag资源的唯一标识(一个字符串,类似人类的指纹)
共存会优先使用Etag
last-Modified只能精确到秒级
如果资源被重复生产,而内容不变,则Etag更精确
三种刷新操作:
正常操作:地址栏输入url,跳转链接,前进后退等
手动刷新:F5,点击刷新按钮,右击菜单刷新
强制刷新:ctrl+F5
不同刷新操作,不同的缓存策略
正常操作:强制缓存有效,协商缓存有效
手动刷新:强制缓存失效,协商缓存有效
强制刷新:强制缓存失效,协商缓存失效
33. 开发环境
git
调试工具
抓包
webpack babel
linux常用命令
34. git
git服务端常见的有github coding.net等
git add.
git checkout xxx // 撤销
git commit -m 'xxx'
git push origin master
git pull origin master
git branch // 查分支
git checkout -b xxx // 切新分支
git checkout xxx 切换分支
git fetch // 当前拉所有分支
git merge xxx // 合并当前分支
git diff /git diff xxx ----修改内容
git status // 查需要提交内容
git log
git stash // 当前改的东西放在一边
git stash pop // 放在一边放出
git show xxx // 提交内容
git config user.name xxx
git config user.email xxx
新建项目
https // 输入用户名,密码
ssh // 需要生成ssh公钥
35. chrome调试工具
36. 抓包
移动端h5页,查看网络请求,需要用工具抓包
windows一般用fiddler
Mac OS一般用charles
手机和电脑连同一个局域网
将手机代理到电脑上
手机浏览网页,即可抓包
查看网络请求
网址代理
https
37. webpack 和babel
ES6模块化,浏览器暂不支持
ES6语法,浏览器并不完全支持
压缩代码,整合代码,以让网页加载更快
38. linux命令
ssh 用户名@IP地址
输入密码
ls // 查看文件夹/文件
ls -a // 查看所有文件
ll // 看列表的形式
clear // 清除
mkdir dir // 创建文件夹
rm -rf dir // 删除文件夹/文件
cd dist/ // 进入目录
../ // 回到上级目录
mv index.html index1.html // 修改文件名
mv index.html dist/index.html // 移动到dist文件夹下
touch index.js // 新建文件
vim index.js // 新建文件并且打开 点esc键 :w 保存 :q 退出 :q! //强制退出
cat pacakage.json // 查看文件
head package.json // 查看文件头
grep "babel" package.json // 查看关键字
39. 运行环境
运行环境即浏览器(server 有nodejs)
下载网页代码,渲染出页面,期间会执行若干JS
保证代码在浏览器总,高效稳定
网页加载过程
性能优化
安全
从输入url到渲染页面的整个过程
window.onload和DOMContentLoaded的区别
加载资源的形式:
html代码
媒体文件,如图片,视频等
javascript css
加载资源的过程:
DNS解析:域名-》IP地址
浏览器根据IP地址向服务器发起HTTP请求(三次握手)
服务器处理http请求,并返回给浏览器
加载资源的渲染
根据HTML代码生成DOM TREE
根据css代码生成CSSOM
将DOM Tree和CSSOM整合形成Render Tree
根据Render Tree渲染页面
遇到
直至把Render Tree渲染完成
为什么建议把css放在head里?
渲染完发现CSSOM,会重新形成Render Tree,重新渲染,网速卡的情况下会感官不好
放head里,好处,生成DOM Tree和CSSOM整合形成Render Tree,一次性渲染完成
为何把建议js放在body最后?
Render Tree渲染页面,遇到
load:页面的全部资源加载完才会执行,包括图片视频等
DOMContentLoaded: DOM渲染即可执行,此时图片视频还可能没有加载完成
DOMContentLoaded比load好
40. 性能优化
多使用内存缓存或者其他方法
减少CPU计算量,减少网络加载耗时
适用于所有编程的性能优化-空间换时间
怎么优化。从何入手?
让加载更快:
减小资源体积:压缩代码
减少访问次数:合并代码,SSR服务器渲染,缓存
使用更快的网络:CDN
缓存:
静态资源加hash后缀,根据文件内容计算hash
文件内容不变,则hash不变,则url不变
url和文件不变,则会自动触发http缓存机制,则返回304
CDN:
SSR:
服务器渲染:将网页和数据一起加载:
非SSR(前后端分离):先加载网页,再加载数据,再渲染数据
让渲染更快:
CSS放在head,JS放在body下面
尽早开始执行JS,用DOMContentLoadad触发
懒加载(图片懒加载,上滑加载更多)
对DOM查询进行缓存
减少频繁DOM操作,合并到一起插入DOM结构
节流throttle防抖debounce
防抖debounce:
function debounce(fn, delay = 500) {
// timer是在闭包中
let timer = null
return function() {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() =>{
fn.apply(this, arguments)
timer = null
}, delay)
}
}
节流throttle:
drag事件,频繁触发,很容易卡顿
function throttle(fn, delay = 500) {
let timer = null
return function() {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
div.addEventListener('drag', throttle(function(e){
console.log(e)
}))
41. 安全
问题:常见的web前端攻击方式有哪些?
XSS跨站请求攻击:
XSRF跨站请求伪造
XSS攻击:
<script>
变为lt; 不会作为脚本被攻击
xss工具,替换
XSRF:
预防:
使用post接口
增加验证。例如密码,短信验证码,指纹
42. 同源策略
源(origin)就是协议、域名和端口号
地址里面的协议、域名和端口号均相同则属于同源
什么是同源策略? 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的
不受同源策略限制的:
页面中的链接,重定向以及表单提交是不会受到同源策略限制的。 跨域资源的引入是可以的。但是js不能读写加载的内容。
如嵌入到页面中的<script src="..."></script>,<img>,<link>,<iframe>等