Appearance
MVVM模式
Model-View-ViewModel是一种软件架构设计模式,包涵三层
View:视图层,也就是用户界面Model:数据模型,这里可以看成请求api返回的数据ViewModel:视图数据层,也是最核心的部分,负责对Model中的数据进行转换处理,做二次封装,以生成符合View层使用预期的视图数据模型,MVVM模式实现了双向绑定,这样只需处理和维护ViewModel,Model变化时,ViewModel会自动更新,而ViewModel变化时,View也会自动更新
vue2.x和vue3.x数据双向绑定的原理
vue是采用-订阅者模式实现数据的数据劫持结合发布双向绑定的。其中vue2.x是通过函数Object.defineProperty()来劫持各个属性的getter和setter,在数据变动时发布消息给订阅者,触发对应的监听回调,而vue3.x是通过proxy实现的。
Object.defineProperty()的缺陷:
无法监测数组变化。但
vue2.x可以使用一部分原生的数组方法,有push、pop、shift、unshift、splice、sort、reverse,实际上是通过拦截器覆盖响应式数组原型上的这些方法实现的 必须遍历对象的每个属性必须深层遍历嵌套对象
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-show和v-if的区别
v-if用于添加或删除Dom,是惰性的,当初始值为false时,则什么都不做,只有在条件第一次为true时才开始局部编译,切换时性能消耗大
v-show则仅仅是css的display属性控制显示隐藏,所以初始渲染消耗大
一般来说,v-if有更高的切换消耗而v-show有更高的初始渲染消耗,因此,如果需要频繁切换则使用v-show,反之使用v-if
computed和watch的区别和使用场景
区别
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树始终为列表渲染设置
key值key值主要用在vue的虚拟Dom算法中,在对比新旧虚拟节点时辨识虚拟节点。在更新子节点时,需要从旧虚拟节点列表中查找与新虚拟节点相同的节点进行更新,如果这个查找过程设置了key值 ,那么查找速度会快很多避免
v-if和v-for一起使用,v-for比v-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个核心属性,分别是state、getters、mutations、actions、modules:
state:定义了应用状态的数据结构,可在此设置数据的初始状态
getters: 类似于计算属性,主要用来从state中派生出一些状态
mutations:其中定义的是唯一更改state数据的方法,且必须是同步函数
actions:用于提交mutation,可包含任意异步操作
modules:允许将单一的store拆分为多个store且同时保存在单一的状态树中
vue-router的导航守卫
全局守卫、路由独享守卫、路由组件内的守卫
服务器渲染(SSR)
大致的意思就是将vue在客户端将标签渲染成html的工作放在服务端完成,然后服务端再将html返回给客户端
优点:更好的SEO、首屏加载速度更快
缺点:开发条件受限、服务器需要处于Node.js server运行环境、更多的服务器负载
vue优化
代码层面的优化
区分
v-if和v-show的使用场景区分
watch和computed的使用场景始终为
v-for循环添加key值,并避免同时使用v-if长列表性能优化:对于数据的纯粹展示,可不需要
vue来劫持数据,在大量数据展示的情况下,能明显减少组件初始化的时间,可使用Object.free()来冻结一个对象事件销毁:如果在js中使用了
addEventListener等方法,组件销毁时是不会自动销毁这些事件的,所以需要在组件销毁时手动移除这些事件的监听,以免造成内存泄露图片资源懒加载:
vue-lazyload插件路由懒加载
第三方插件的按需引入
优化无限列表性能:
vue-virtual-scroll-list、vue-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查找性能瓶颈