Skip to content

MVVM模式

Model-View-ViewModel是一种软件架构设计模式,包涵三层

  • View:视图层,也就是用户界面

  • Model:数据模型,这里可以看成请求api返回的数据

  • ViewModel:视图数据层,也是最核心的部分,负责对Model中的数据进行转换处理,做二次封装,以生成符合View层使用预期的视图数据模型,MVVM模式实现了双向绑定,这样只需处理和维护ViewModelModel变化时,ViewModel会自动更新,而ViewModel变化时,View也会自动更新

vue2.xvue3.x数据双向绑定的原理

vue是采用-订阅者模式实现数据的数据劫持结合发布双向绑定的。其中vue2.x是通过函数Object.defineProperty()来劫持各个属性的gettersetter,在数据变动时发布消息给订阅者,触发对应的监听回调,而vue3.x是通过proxy实现的。

Object.defineProperty()的缺陷:

  • 无法监测数组变化。但vue2.x可以使用一部分原生的数组方法,有pushpopshiftunshiftsplicesortreverse,实际上是通过拦截器覆盖响应式数组原型上的这些方法实现的 必须遍历对象的每个属性

  • 必须深层遍历嵌套对象

Proxy的优点:

可以直接监听对象和数组的变化,多达13种拦截方法,不必再写hack实现数组的监听,而且作为新标准将受到浏览器厂商重点持续的性能优化。

Proxy只会代理对象的第一层,可以判断当前Reflet.get的返回值是否为Object,如果是则再通过reactive方法做代理,这样就实现了深度监测

Proxy监测数组的时候可能触发多次get/set,可以判断key是否为当前代理对象target自身属性,也可以判断旧值与新值是否相等,只要满足上述两个条件之一,才执行trigger

生命周期

berforeCreate:实例创建前,此时data、methods、computed、watch上的数据和方法均不能访问

create:实例创建完成,此时已完成数据观测,可更改数据,但不会触发undated函数,无法访问Dom,如果非要可以通过vm.$nextTick来访问

beforeMount:挂载前,虚拟Dom创建完成,即将渲染,可更改数据,但不会触发undated函数

Mounted:挂载完成,真实Dom挂载完毕,数据完成双向绑定,可以访问Dom,一般网络请求放这里,但如果是服务器渲染就得放在created

beforeUpdate:更新前,也就是响应式数据发生更新,虚拟Dom重新渲染之前触发可在当前阶段进行更改数据,不会造成重渲染

updated:更新完成后,此时Dom已完成更新,要避免在此期间更改数据,可能会导致无限循环的更新

boforeDestroy:实例销毁前,可以在此阶段进行善后收尾工作,如清除计时器等

destroyed:实例销毁后

vue.nextTick()

定义:在下次Dom更新循环结束之后执行延迟回调,在修改数据之后立即使用这个方法,获取更新后的Dom

vue实现响应式并不是数据发生变化后Dom立即变化,而是异步执行Dom更新的。比如在created阶段是获取不到Dom的,但在该阶段调用nextTick方法,当下一次Dom更新时就会触发这个方法达到操作Dom的目的

一句话概括就是在数据变化后需要操作Dom时都应该放进该方法中

v-showv-if的区别

v-if用于添加或删除Dom,是惰性的,当初始值为false时,则什么都不做,只有在条件第一次为true时才开始局部编译,切换时性能消耗大

v-show则仅仅是cssdisplay属性控制显示隐藏,所以初始渲染消耗大

一般来说,v-if有更高的切换消耗而v-show有更高的初始渲染消耗,因此,如果需要频繁切换则使用v-show,反之使用v-if

computedwatch的区别和使用场景

区别

computed:计算属性,依赖其他属性值,并且computed的值有缓存,只有它依赖的属性值发生变化,下一次获取computed的值时才会重新计算

watch:更多的是观察的作用,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作

使用场景

  • computed主要用于对同步数据的处理,当需要进行数值计算并依赖于其他数据时,应该使用computed,因为可以利用computed的缓存特性,避免每次获取值时,都要重新计算

  • 当需要在数据变化时执行异步或开销较大的操作时,应该用watch,使用watch选项允许我们执行异步操作,限制我们执行该操作的频率,并可在最终结果前设置中间状态

keep-alive

keep-alive可以实现组件缓存,当组件切换时不会对当前组件进行卸载。常用的两个属性include/exclude,允许组件有条件的进行缓存。两个生命周期activated/deactivated,用来得知当前组件是否处于活跃状态

组件中的data为什么是一个函数

组件是可复用的vue实例,当一个组件被创建好后不管被复用了多少次,组件中的data数据都应该是相互隔离、互不影响的,而如果data直接是一个对象的话,则所有的实例将共享一个数据对象

  • 虚拟Dom的实现原理 用js对象模拟真实Dom树,对真实Dom进行抽象 diff算法:比较两颗虚拟Dom树的差异 patch算法:将两个虚拟Dom对象的差异应用到真正的Dom

  • 始终为列表渲染设置keykey值主要用在vue的虚拟Dom算法中,在对比新旧虚拟节点时辨识虚拟节点。在更新子节点时,需要从旧虚拟节点列表中查找与新虚拟节点相同的节点进行更新,如果这个查找过程设置了key值 ,那么查找速度会快很多

  • 避免v-ifv-for一起使用,v-forv-if有更高的优先级,这意味着v-if将分别重复运行于每个v-for循环

vue通信方式

  • 仅限于父子间的通信

props/$emit:父组件通过props向子组件传值,子组件通过$emit通知父组件

$parent/$children与ref:其中ref如果是在普通的Dom元素上使用,引用的还就是Dom元素,如果是用在子组件上,指向的就是组件实例

$parent/$children:访问父/子实例

  • 适用于隔代组件间通信:

$attrs/$listeners

provide/inject

  • 任何组件间的通信,包括父子、兄弟、跨级

EventBus($emit/$on):通过一个空的Vue实例作为中央事件总线,用它来触发事件和监听事件,可以巧妙而轻量地实现任何组件间的通信

vuex:全局状态管理

vuex

vuex是一个专为vue.js应用程序开发的状态管理插件,采用集中式存储管理应用所有组件的状态,而更改状态的唯一方法是提交mutation,包含了5个核心属性,分别是stategettersmutationsactionsmodules:

state:定义了应用状态的数据结构,可在此设置数据的初始状态

getters: 类似于计算属性,主要用来从state中派生出一些状态

mutations:其中定义的是唯一更改state数据的方法,且必须是同步函数

actions:用于提交mutation,可包含任意异步操作

modules:允许将单一的store拆分为多个store且同时保存在单一的状态树中

vue-router的导航守卫

全局守卫、路由独享守卫、路由组件内的守卫

服务器渲染(SSR

大致的意思就是将vue在客户端将标签渲染成html的工作放在服务端完成,然后服务端再将html返回给客户端

优点:更好的SEO、首屏加载速度更快

缺点:开发条件受限、服务器需要处于Node.js server运行环境、更多的服务器负载

vue优化

代码层面的优化

  • 区分v-ifv-show的使用场景

  • 区分watchcomputed的使用场景

  • 始终为v-for循环添加key值,并避免同时使用v-if

  • 长列表性能优化:对于数据的纯粹展示,可不需要vue来劫持数据,在大量数据展示的情况下,能明显减少组件初始化的时间,可使用Object.free()来冻结一个对象

  • 事件销毁:如果在js中使用了addEventListener等方法,组件销毁时是不会自动销毁这些事件的,所以需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露

  • 图片资源懒加载:vue-lazyload插件

  • 路由懒加载

  • 第三方插件的按需引入

  • 优化无限列表性能:vue-virtual-scroll-listvue-virtual-scroller插件

  • 服务器渲染(SSR)和预渲染(prerender-spa-plugin插件)

webpack层面的优化

  • 图片压缩:image-webpack-loader插件

  • 减少ES6转为ES5的冗余代码:babel-plugin-transform-runtime插件

  • 提取公共代码:CommomChunkPlugin插件

  • 模板预编译

  • 提取组件的css

  • 优化SourceMap:开发环境推荐:cheap-module-eval-source-map;生产环境推荐:cheap-module-source-map

  • 构建结果输出分析:webpack-bundle-analyzer插件

  • vue项目的编译优化:Vue项目Webpack优化实践,构建效率提高50%

基础的web技术优化

  • 开启gzip压缩

  • 浏览器缓存

  • 使用cdn

  • 使用Chrome Performance查找性能瓶颈