# Vue2.x 知识点
# 1.Vue 基础
# 1.1 生命周期
- 1.创建
- 1.1 获取
dom前:beforeCreated、created、beforeMount - 1.2 获取
dom后:mounted、activated
- 1.1 获取
- 2.更新:
beforeUpdate、updated - 3.销毁:
beforeDestroy、destroyed、deactivated - 4.错误:
errorCaptured
# 1.2 组件通信
- 1.父子:
props、emit、$slot、$attrs、$listeners、$refs、$parent、$chindren、provide、inject、bus - 2.兄弟:借助
1、2实现 - 3.跨组件:
vuex、provide、inject、bus
# 1.3 基础 API、属性
- 1.extend 能做什么
这个 API 很少用到,作用是扩展组件生成一个构造器,通常会与$mount一起使用。
// 创建组件构造器
let Component = Vue.extend({
template: `<div>test</div>`,
})
// 挂载到#app上
new Component().$mount("#app")
// 除了上面的方式,还可以用来扩展已有的组件
let SuperComponent = Vue.extend(Component)
new SuperComponent({
created() {
console.log(1)
},
})
new SuperComponent().$mount("#app")
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.4 mixin 和 mixins 区别
# 1.5 computed 和 watch 区别
computed是懒加载版的watch
# 1.6 keep-alive 作用
- 缓存组件实例,当再次需要使用时,直接从内存中拿取,不必经历各种复杂的计算过程,大大提高了性能
- 在被 keep-alive 包含的组件/路由,会多出两个生命周期:activated 和 deactiated
- actived 在组件第一次渲染时会被调用,之后每次缓存组件被激活时调用,调用机制:第一次进入缓存路由/组件,在 mounted 后面,beforRouteEnter 守卫传给 next 的回调函数之前调用
# 1.7 v-show 与 v-if 区别
v-show通过控制样式display:none来实现组件隐藏的v-if通过直接移除组件来实现组件隐藏的
# 1.8 data 可以使用对象吗
- 根组件可以
- 其他组件不行
# 1.9 spa 如何优化加载速度
- 1.减少入口文件的体积
- 2.静态资源本地缓存
- 3.开启 Gzip 压缩
- 4.使用 ssr,nuxt.js
# 1.10 组件化的思想
- 我们在各个页面开发的时候,会产生很多重复的功能
- 1.我们在各个页面开发的时候,会产生很多重复的功能,比如,element 中的 xxx,像这种纯粹非页面的 UI,便成为我们常用 UI 组件,最初的前端组件也就仅仅值得是 UI 组件
- 2.随着业务逻辑变得越来越多时,我们就想要我们的组件可以处理很多事,这就是我们常说的组件化,这个组件就不是 UI 组件了,而是包含具体业务的业务组件
- 3.这种开发思想就是分而治之。最大程度降低开发难度和维护成本的效果,并且可以多人协作,每人写不同的组件,最后像搭积木一样把它构成一个页面
# 1.11 框架区别
- vue 与 AngularJS 的区别
相同点:都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。
不同点:AngularJS 的学习成本高,比如增加了 Dependency Injection 特性,而 Vue.js 本身提供的 API 都比较简单、直观;在性能上,AngularJS 依赖对数据做脏检查,所以 Watcher 越多越慢;Vue.js 使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。
- vue 与 React 的区别
相同点:React 采用特殊的 JSX 语法,Vue.js 在组件开发中也推崇编写.vue 特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数 AJAX,Route 等功能到核心包,而是以插件的方式加载;在组件开发中都支持 mixins 的特性。
不同点:React 采用的 Virtual DOM 会对渲染出来的结果做脏检查;Vue.js 在模板中提供了指令,过滤器等,可以非常方便,快捷地操作 Virtual DOM。
# 2.Vue 原理
# 2.1 介绍下 MVVM
- M:model 数据模型
- V:view 界面
- VM:作为桥梁负责沟通,view 和 model
- 只关心数据的流传,减少强耦合性,最关键的就是数据的双向绑定
- 关键步骤:
- 1.实现数据监听器 Observer,用 object.defineProperty()重写数组的 get/set。数据更新就在 set 中通知订阅者更新数据。
- 2.实现模板编译 compiler,深度遍历 dom 树,对每个元素节点的指令模板替换数据及订阅数据。
- 3.实现 watch 用于连接 Observer 和 Compiler,能够订阅并接受每一个属性的变动的通知,执行指令绑定对的响应的回调函数,从而更新数据。
- 4.MVC 和 MVVM 其实区别并不大。都是一种设计思想,主要是 MVC 中 Controller 演变成 MVVM 中的 ViewMode,mvvm 主要解决了 MVC 中大量的 Dom 操作使页面渲染性能降低。
# 2.2 响应式原理
- 采用数据劫持结合发布订阅,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。当把一个普通 JavaScript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty()将他们转换为 getter/sertter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
- Vue 的数据双向绑定,将 MVVM 作为数据绑定的入口,整合 Observer,Compile 和 Watcher 三者,通过 Observer 来监听自己的 model 的数据变化,通过 Compiler 之间的通信桥梁,达到数据变化-->视图更新;视图交互变化(input)-->数据 model 变更双向绑定的效果。
# 2.3 响应式的缺陷
- 1.不能拦截数组,vue 内部通过重新函数解决这个问题,但是有些操作还是不能拦截(如:通过下标修改、访问数据,访问 length)
- 2.对象上删除数据不能拦截,vue 提供
$delete来解决这个问题 - 3.对象上设置新属性不能拦截,vue 提供
$set来解决这个问题
# 2.4 编译原理
Vue 会通过编译器将模板通过几个阶段最终编译为render函数,然后通过执行render函数生成 Virtual DOM 最终映射为真实 DOM
编译阶段大致分为三个阶段:
- 将模板解析为 AST
- 优化 AST
- 将 AST 转换为
reder函数
# 2.5 diff 算法
旧节点和新节点上头尾分别设置指针,while循环中比较节点头-头、头-尾、尾头、尾尾,有相同向内移动指针,然后遍历新节点在旧节点中有就复用没有就创建,遍历旧节点有剩余就删除
# 2.6 nextTick 原理
nextTick可以让我们在下次 DOM 更新循环结束之后执行延迟回调,用于获得更新后的 DOM。
在 Vue 2.4 之前都是使用的 microtasks,但是 microtasks 的优先级过高,在某些情况下可能会出现比事件冒泡更快的情况,但如果都使用 macrotasks 又可能出现渲染性能问题。所以在新版中,会默认使用 microtasks,但在特殊情况下会使用 macrotasks,比如 v-on。
对于实现 macrotasks 会先判断是否能用setImmediate,不能的话降级为MessageChannel,以上都不行的话就使用setTimeout
if (typeof setImmediate !== "undefined" && isNative(setImmediate)) {
macroTimerFunc = () => {
setImmediate(flushCallbacks)
}
}else if(
typeof MessageChannel !== 'undefined' &&
(isNative(MessageChannel) ||
MwssageChannel.toString() === '[object MessageChannelConstructor]')
){
const channel = new MessageChannel()
const port = channel.port2
channel.port1.onmessage = flushCallbacks
macroTimerFunc = () =>{
port.postMessage(1)
}else {
macroTimerFunc=()=>{
setTimeout(flushCallbacks,0)
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 3.Vue-Router
# 3.1 路由钩子
- 全局导航钩子
- router.beforeEach(to,from,next)
- router.beforeResolve(to,from,next)
- router.afterEach(to,from,next)
- 组件内钩子
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
- 单独路由独享钩子
- beforeEnter
# 3.2 路由实现
- hash 模式: 在浏览器中符号“#”,#以及#后面的字符称之为 hash,用 window.location.hash 读取。 特点:hash 虽然在 URL 中,但不被包括在 HTTP 请求中;用来指导浏览器动作,对服务端安全无用,hash 不会重加载页面。
- history 模式: history 采用 HTML5 的新特性;且提供了两个新方法: pushState(), replaceState()可以对浏览器历史记录栈进行修改,以及 popState 事件的监听到状态变更。
# 4.Vuex
# 4.1 vuex 是什么?怎么使用?
只用来读取的状态集中放在 store 中; 改变状态的方式是提交 mutations,这是个同步的事物; 异步逻辑应该封装在 action 中。
在 main.js 引入 store,注入。新建了一个目录 store,… export 。 state:Vuex 使用单一状态树,即每个应用将仅仅包含一个 store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations:mutations 定义的方法动态修改 Vuex 的 store 中的状态或数据。
getters:类似 vue 的计算属性,主要用来过滤一些数据。
action:actions 可以理解为通过将 mutations 里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
# 4.2 哪种功能场景使用它?
单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车