什么是Vue
Vue是构建用户界面的 JavasScript 的 MVVM 框架。
那么到底什么是 MVVM

- M(Model):数据层;例如 Vue2 实例中的 data
- V(View):视图(DOM)
- VM(ViewModel):Vue胶水层代码;它负责 监听数据的变化 和 视图的更新,同时也是
Model数据 和View视图通信的一个桥梁
MVVM 又叫数据驱动视图,所以视图的改变源于数据的更新。

Vue 在实例化的过程中会对遍历传给 实例化对象选项中的 data选项 遍历其所有属性 并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
Vue 最重要的两个 function 监听 Observer 和 编译 Compile
Observer
- Observer 基本干了什么事情
- 劫持并监听所有属性
- 在 Observer 函数中
- 采用的方式
- Vue2 Object.defineProperty
- Vue3 new Proxy
- 劫持并监听所有属性
export class Observer {
value: any;
dep: Dep;
vmCount: number;
constructor (value: any) {
this.value = value
// 一个 Dep 对象的实例,Watcher 和 Observer 之间的桥梁
this.dep = new Dep()
this.vmCount = 0
// 把自身 this 添加到 value 的 __ob__ 属性上
def(value, '__ob__', this)
// 对 value 的类型进行判断
if (Array.isArray(value)) {
if (hasProto) {
protoAugment(value, arrayMethods)
} else {
copyAugment(value, arrayMethods, arrayKeys)
}
this.observeArray(value)
} else {
this.walk(value)
}
}
}
常见问题
data为什么需要是个函数- 因为
js的对象是按引用传递的,如果使用对象的话,会导致组件内数据无法保持唯一,可能会被其他组件数据修改,所以需要使用函数,每次都重新创建一个新的对象实现。
- 因为
响应式原理
通过
definePropery对data内的属性遍历添加getter、setter属性,通过watcher对Dep进行依赖收集管理,内部会通过Dep.target去维护一个当前的watcher,当数据更新的时候会去执行dep.notify方法,依次遍历当前dep内的watcher进行数据更新。Observer用于添加getter和setter。Dep进行依赖收集 (收集的依赖就是watcher)。Watcher主要负责保存依赖,从而在数据更新的时候,触发渲染。
- data watcher
- watch watcher
- computed watcher
- 在实例上保存了个
lazy和dirty属性。 - 如果当前的
dirty为true,说明就需要重新计算,则调用watcher.evaluate方法进行计算。 watcher创建的时候,默认是不会调用get方法进行依赖收集。- 只有在数据发生变化的时候,会去调用
watcher.update, 然后再这里面调用watcher.run,进而去调用get方法收集依赖,或者数据发生变化的时候,也会重新收集依赖。
- 在实例上保存了个
computed
- 调用
initComputed进行初始化,对computed内的每个对象创建一个watcher。 - 如果
computed是个函数,就调用createComputedGetter否则调用createGetterInvoker,并通过defineProperty挂载到实例上,重写get方法。
watch
- 调用
initWatch进行初始化,并对watch内的每个属性,创建一个watcher。 - 如果
val是对象,贼调用val.handler,是string,则从this中获取,否则val就是个函数 - 对
watch的每个属性调用vm.$watch进行处理 - 依然创建一个watcher,如果当前 watch 有 immediate 属性,则立刻执行
性能指标
FP(First Paint)首次绘制 FCP (First Contentful Paint) 首次内容绘制 LCP(Largest Contentful Paint)最大内容绘制 DCL (DocumentContentLoaded) dom加载完成 L (Onload)页面加载完成 TTI(Time To Interactive)可交互 TBT (Total Blocking Time)页面阻塞总时长 FID (First Input Delay)首次输入延迟 CLS (Cumlative Layout Shift)累计布局偏移 SI (Speed Index) 首次显示页面可见部分的平均时间
雅虎35条军规前端性能优化之雅虎35条军规
服务器
- 使用cdn
- 使用浏览器缓存
- 启用gzip
- 配置etag
- ajax使用get请求(get可以被缓存,post不会)
- 避免图片src为空
- 尽早输出内容(服务端渲染)
页面内容
- 减少http请求
- 减少dns查询
- 避免重定向
- 缓存ajax请求
- 延迟加载
- 预加载
- 减少dom元素数量
- 划分内容到不同域名
- 减少iframe使用
- 减少404
- 保持单个文件小于25kb
- 打包内容为分段multipart文档
Cookie
- 减少cookie大小
- 静态资源使用无cookie的域名
图片
- 尽可能使用webp
- css sprite(雪碧图)
- 使用体积小,可缓存的favicon.ico
js
- script放页面底部
- 使用外部 js 和 css
- 压缩 css js
- 删除重复脚本
- 减少dom操作
- 使用高效的事件处理
css
- 把样式表放在head内
- 不用使用css表达式
- 使用link代替@import
- 不要使用filter(不是css3的filter,ie的东西)
重排重绘的操作读写分离 getComputedStyle currentStyle
重排: 页面初始渲染,这是开销最大的一次重排 添加/删除可见的DOM元素 改变元素位置 改变元素尺寸,比如边距、填充、边框、宽度和高度等 改变元素内容,比如文字数量,图片大小等 改变元素字体大小 改变浏览器窗口尺寸,比如resize事件发生时
重绘: 当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘
1.HTML 被 HTML 解析器解析成 DOM 树; 2.CSS 被 CSS 解析器解析成 CSSOM 树; 3.结合 DOM 树和 CSSOM 树,生成一棵渲染树(Render Tree),这一过程称为 Attachment; 4.生成布局(flow),浏览器在屏幕上“画”出渲染树中的所有节点; 5.将布局绘制(paint)在屏幕上,显示出整个页面。 第四步和第五步是最耗时的部分,这两步合起来,就是我们通常所说的渲染。