# Review

# css

# 垂直居中

display:flex; justify-content:center; align-items:center;
display:inner; text-align:center;
display:grid; justify-content:center;
display:grid; place-items:center;
position:relative; margin:auto;
position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
display:flex; margin:auto;

# BFC

overflow:hidden;
position: absolute;或者position: fixed;
display: flex;
display: grid;

# js

# event loop

同步任务(script)=>微任务(promise.then().catch()await,process.nextTick())=>宏任务(setTimeout()setInterval(),IO操作(fetch,XMLHttpRequest),UI交互事件(点击,滚动,输入))

宏任务队列和微任务队列,系统首先开始执行主线,遇到宏任务,加入到宏任务队列,遇到微任务也加入微任务队列,然后主线往下执行,直到主线执行完毕,系统会查看微任务队列中是否存在微任务,如果存在,则将所有微任务也按主线方式执行完成,然后清空微任务,开始将宏任务队列中的第一个宏任务设置为主线继续执行,直到所有的宏任务队列执行清空完成。

在 JavaScript 中,PromisesetTimeout 等任务的执行遵循 Event Loop(事件循环) 的规则。以下是宏任务(macrotasks)和微任务(microtasks)在事件循环中的执行步骤:


# 1. 任务分类

  • 宏任务(Macrotask)
    • Examples: setTimeoutsetIntervalsetImmediate (Node.js)、I/O 操作、UI 渲染。
  • 微任务(Microtask)
    • Examples: Promise.thencatchfinallyMutationObserverqueueMicrotask

微任务的优先级高于宏任务,每次宏任务执行完成后,会优先清空微任务队列。


# 2. 执行步骤(事件循环机制)

  1. 执行全局代码:
    • 从同步代码开始,直接依次执行,进入调用栈。
  2. 处理微任务:
    • 同步代码执行结束后,清空当前产生的所有微任务队列。
  3. 执行宏任务:
    • 从宏任务队列中取出一个任务执行,然后再次检查微任务。
  4. 重复步骤 2 和 3:
    • 不断重复,直到队列为空。
console.log('1'); // 同步任务
setTimeout(() => { 
    console.log('3'); // 宏任务 
}, 0);
logger = () => {
    console.log('2'); // 普通函数,直接执行
}
async function asfn(params) {
    console.log('4'); // 同步任务
    await logger();   // 调用 logger() 是同步任务,但 await 会暂停后续代码并将其转成微任务
    console.log('5'); // 微任务
}
asfn();
const p = new Promise((resolve, reject) => {
    console.log('6'); // 同步任务
    resolve('success'); // 执行 resolve,触发微任务
    console.log('7'); // 同步任务
});
p.then((res) => {
    console.log(res); // 微任务
});

# promise

promise是异步编程的一种解决方案 微任务

有padding进行中、 fulfilled已成功 、reject已失败三个状态

解决回调地狱 1通过链式调用.then 2多次调用async、await方法 使代码读起来像是同步的

promise本身是同步,.then.catch.finally和await这些是异步的

async和await ,async return 一个promise对象 await后面不管跟着什么 都会阻塞后面的代码 会先执行外面的同步的代码

# websocket

客户端和服务器之间建立持久连接的协议 双向实时通信

连接 => 更新数据 => beforedestory断开连接

心跳机制 一般30s~60s

一方发送PING 一方发送PONG ,指定时间没有接到PONG消息认为连接断开,重新连接或关闭

# 内存泄露

程序运行时未能释放不再使用的内存 导致内存不断被占用 从而降低性能甚至导致奔溃

未清除的定时器、事件监听器、闭包、全局变量、大型数据结构

beforedestory里去解除绑定 或者赋值为null

意外的全局变量: 无法被回收
定时器: 未被正确关闭,导致所引用的外部变量无法被释放
事件监听: 没有正确销毁 (低版本浏览器可能出现)
闭包: 会导致父级中的变量无法被释放
dom 引用: dom 元素被删除时,内存中的引用未被正确清空

# 闭包

嵌套函数被导出外部执行 函数内部的值会被保存到内存中 不被销毁

优点 延长了变量的生命周期 利用闭包访问函数中的变量

缺点 一直保存在内存中直到页面关闭 解决 在不需要的时候清除引用 不必要不使用闭包

# vue2

# keep-alive

# 介绍

keep-alive可以缓存组件的v-node

在组件反复切换的时候,去复用缓存的v-node,可以提高页面的渲染效率

可以防止组件的切换中导致组件状态变化

# 属性

# include

记录的是哪些组件可以被缓存

# exclude

哪些组件不能被缓存

# max

可以缓存组件的最大数量

还提供两个生命周期钩子函数

actived 在激活的时候 mounted之后

dectived 在失活的时候

# 实现原理

keep-alive内部保存了一个key的数组和一个组件缓存对象

# v-if和v-show

v-if是控制真实的dom渲染和摧毁 性能消耗较大

v-show是控制css的display 初始会渲染 适合经常切换的场景

# vue3

# 浏览器

# 从输入 url 到展示的过程

  • DNS 解析
  • TCP 三次握手
  • 发送请求,分析 url,设置请求报文(头,主体)
  • 服务器返回请求的文件 (html)
  • 浏览器渲染
    • HTML parser --> DOM Tree
      • 标记化算法,进行元素状态的标记
      • dom 树构建
    • CSS parser --> Style Tree
      • 解析 css 代码,生成样式树
    • attachment --> Render Tree
      • 结合 dom树 与 style树,生成渲染树
    • layout: 布局
    • GPU painting: 像素绘制页面

# 本地存储

Cookie localStorage sessionStorage indexedDB
容量大小 4kb左右 5M左右 5M左右 无限容量
过期时间 只在设置的过期时间之前一直有效, 即使窗口或者浏览器关闭 始终有效 当前浏览器窗口关闭前有效 始终有效
存储方式 浏览器和服务器间来回传递 本地保存 本地保存 本地保存
作用域 在同源窗口中共享 在同源窗口中共享 在同源窗口并且同一窗口中共享 在同源窗口中共享

# 项目优化

# 1 资源文件方向

压缩缓存

懒加载异步加载

使用iconfont替代图标

精灵图雪碧图

img标签的loading="lazy"进入视口才加载

渐进式加载图片 先加载模糊的 加上css过渡效果高清加载完成再替换

# 2 网络请求方向

减少请求次数

检查视口高度按需发送请求

# 3 代码方向

优化代码性能 优化算法
减少dom操作 应用到虚拟dom上 最后一次性应用到dom上 缓存访问过的元素
通过async defer 异步加载文件
虚拟滚动
事件委托到父元素上
放弃js动画,用canvas动画和css动画

语法使用上 v-if,v-show .v-for-v-if

# 4 webpack

缩小代码体积 资源体积

# 5 ssr服务端渲染

使用nuxt或nextjs 优点 首屏加载快 有利于seo 缺点 服务器消耗大

# 首屏加载

减少网络请求

使用缓存

路由懒加载 图片懒加载 异步加载script标签

服务端渲染

体验 增加骨架屏 增加loading