Vue
对 Vue 的了解
Vue 是一个构建数据驱动的渐进性框架,指标是通过 API 实现 响应数据绑定 和 视图更新
Vue 的两大外围
- 数据驱动
-
组件零碎
Vue 生命周期
Vue 实例从创立到销毁的过程
graph LR 开始创立 --> 初始化数据 --> 编译模板 --> 挂载 DOM--> 渲染 --> 更新 --> 渲染; 更新 --> 卸载
生命周期的作用
生命周期中有多个事件钩子,能让开发者在管制整个 vue 实例的过程时更容易造成良好的逻辑判断
created
和mounted
created | mounted | |
---|---|---|
调用机会 | 模板渲染成 HTML 前 | 模板渲染成 HTML 后 |
常见作用 | 初始化属性值,再渲染成视图 | 操作 DOM 节点 |
定时器
在 beforeDestroy()
革除
clearInterval(this.timer);
this.timer = null;
v-model
的应用
用于表单数据的双向绑定,其实是语法糖,背地做了两个操作:
- v-bind 绑定 value 属性
-
v-on 绑定 input 事件
Vue 响应式 (双向数据) 原理
通过 数据劫持 联合 公布订阅模式 的形式来实现
- Vue2:通过 Object.defineProperty() 来劫持各个属性的 setter、getter,在数据变动时公布音讯给订阅者,触发相应的监听回调
-
Vue3:仅仅是将数据劫持的形式由 Object.defineProperty 更改为 ES6 的 Proxy 代理
Vue3 绝对 Vue2 的优化
- 双向数据绑定方面:
Vue2 的 object.defineProperty 一次只能劫持对象的单个属性,从而须要通过递归 + 遍历对每个对象的每个属性进行数据监控;如果属性值是对象的话,还须要深度遍历
而 Vue3.0 中的 proxy 能够一次性地劫持对象的所有属性的 setter、getter,还能够代理数组,也能够代理动静增加的属性,有 13 种劫持操作 - 性能方面快 1.2~2 倍:
(1) diff 办法优化
vue2 中的虚构 dom 是全量的比照(每个节点不管写动态还是动静的都会比拟)
vue3 新增了动态标记(patchflag)与上次虚构节点比照时,只比照带有 patch flag 的节点(动态数据所在的节点);可通过 flag 信息得悉以后节点要比照的具体内容
(2) 动态晋升
vue2 无论元素是否参加更新,每次都会从新创立而后再渲染
vue3 对于不参加更新的元素,会做动态晋升,只会被创立一次,在渲染时间接复用即可
(3) 工夫侦听器缓存
默认状况下 onClick 会被视为动静绑定,所以每次都会追踪它的变动
然而因为是同一个函数,所以不必追踪变动,间接缓存起来复用即可
(4) ssr 渲染
- 按需编译,体积比 vue2.x 更小
- 组合 API(相似 react hooks)
- 更好的 Ts 反对
- 裸露了自定义渲染 API
- 更先进的组件
-
Fragment: 模板能够有多个根元素
虚构 DOM
虚构 DOM 绝对于浏览器所渲染进去的实在 DOM,在 React,Vue 等技术呈现之前,扭转页面展现内容只能遍历查问 DOM 树找到须要批改的 DOM, 而后批改款式行为或者构造,来更新 UI,然而这种形式相当耗费计算资源,每次查问 DOM 简直都须要遍历整棵 DOM 树,因而建设一个与实在 DOM 树对应的虚构 DOM 对象(JavaScript 对象),以对象嵌套的形式来示意 DOM 树,那么每次 DOM 的更改就变成了对象属性的更改,这样一来就能通过 diff 算法查找变动要比查问实在的 DOM 树的性能开销小
<template>
渲染过程graph TD 将 template 标签外面的内容编译成 render 函数 --> 挂载实例: 依据 render 函数的根节点递归生成虚构 DOM 树 --> 通过 diff 算法比照虚构 DOM, 渲染到实在 DOM--> 新的 DOM 操作使得 DOM 树产生扭转 --> 通过 diff 算法比照虚构 DOM, 渲染到实在 DOM
key 的作用
为了高效的更新虚构 DOM
给虚构 DOM 的每个节点 VNode 增加惟一 id, 让其能够依附 key, 更疾速精确地拿到 oldVnode 中对应的 VNode
【设置 key 不举荐应用 index 或者随机数,因为增删子项的时候损耗性能较大】
v-if
和v-show
- v-if 在 DOM 层面决定元素是否存在,会引起重排重绘
-
v-show 在 CSS 层面决定是否将元素渲染进去(实际上该元素始终存在)
v-if
和v-for
优先级
v-if |
v-for |
|
---|---|---|
Vue 2 | 优先 | |
Vue 3 | 优先 |
解决方案 :
- 父元素应用 v -if,子元素应用 v -for
- 应用计算属性
computed
computed() {list() {return [1, 2, 3].filter(item => item !== 2);
}
}
data
是个函数并且返回一个对象 / data
为什么要用 return
因为一个组件可能会多处调用,每次调用会执行 data 函数并返回新的数据对象,因而这样能够防止多处调用之间的数据净化
Vue 如何监听键盘事件
- @keyup. 办法
-
addEventListener
组件通信
- 父子的传参及办法调用:props / $emit、$parent / $children
- 祖孙的传参:provide / inject API、$attrs / $listeners
- 兄弟的传参:bus.js、Vuex
- 路由的传参:query、params
父子 | 祖孙 / 隔代 | 兄弟 | |
---|---|---|---|
props / $emit | √ | ||
ref 与 $parent / $children | √ | ||
$attrs / $listeners | √ | ||
provide / inject | √ | ||
EventBus($emit / $on) | √ | √ | √ |
Vuex | √ | √ | √ |
localStorage/Cookie 等都能够
删除数组用 delete 和 Vue.delete 的区别
-
delete:只是被删除数组成员变为 empty / undefined,其余元素键值不变
- Vue.delete:间接删了数组成员,并扭转了数组的键值
(对象是响应式的,确保删除能触发更新视图,这个办法次要用于避开 Vue 不能检测到属性被删除的限度)
- Vue.delete:间接删了数组成员,并扭转了数组的键值
计算属性 computed
和属性检测watch
cpmputed:当且仅当计算属性依赖的 data 扭转时才会主动计算
computed |
watch |
|
---|---|---|
首次运行 | √ | × |
默认依赖 | 深度(举荐应用) | 浅度 |
调用时 | 在模板渲染 | 只需批改元数据 |
适合性 | 筛选、不可异步 | 开销较大、异步操作 |
特色 | 依据页面变动而变动(用于计算) | 监听页面状态而变动(用于监听) |
Vue 组件封装过程
graph LR
Vue.extend  创立组件 -->Vue.component  注册组件
v-for
后应用 this.$refs
报错 domundefined
组件初始化到第一次渲染实现的 mounted 周期里,只是渲染了组件模板的静态数据,并没有初始化动静绑定的 dom,所以在 mounted 周期外面操作获取不到 dom
解决办法:
- 把 this.$nextTick 放在获取到 v -for 绑定的数据并赋值之后,也就是触发响应式更新之后再进行操作
-
把操作 dom 的操作放到 updated 生命周期里,然而这样每次更新视图都会触发该操作
scoped
的实现原理 - 通过 PostCSS 给所有 dom 都增加了惟一的动静属性
-
通过 PostCSS 也给 css 选择器额定增加对应的属性选择器,来抉择组件中的 dom
插槽
- 默认插槽
- 具名插槽
-
作用域插槽
Vue CLI
src 目录每个文件夹和文件的用法
- assets 文件夹是放动态资源;
- components 是放组件;
- router 是定义路由相干的配置;
- app.vue 是一个利用主组件;
-
main.js 是入口文件
static 和 assets 的区别
原理:webpack 如何解决动态资源
static assets 内容 类库 我的项目资源 资源 间接援用 被 webpack 打包
(static 放他人家的资源,assets 放本人家的资源)
引入第三方库
- 绝对路径间接引入
- 在 webpack 中配置
alias
[ˈeɪliəs] -
在 webpack 中配置
plugins
[ˈplu:genz]Vue-Router
路由实现原理
- 利用 URL 中的 hash(“#”)
-
利用 History interface 在 HTML5 中新增的办法
hash 模式和 history 模式
hash 模式
history 模式
浏览器反对版本 IE、低版本 HTML5 新推出的 API 刷新 从新加载 404 URL 中是否带 # √ × # 前面的 hash 变动 不会从新加载,会触发 hashchange 事件渲染对应内容 从新加载,会触发 popState 事件渲染对应内容
传参
- name 传参
- URL 传参
<router-link>
的 to 传参-
用 path 匹配路由,通过 query 传参
二级路由 / 嵌套路由哦
应用路由导航
<router-link>
和路由容器<router-view>
,配置 children路由守卫触发流程
-
不同组件(A 组件跳转到 B 组件)
graph TD 触发导航 --> 调用 A 组件的路由守卫 beforeRouteLeave--> 调用全局路由前置守卫 beforeEach--> 调用 B 路由独享守卫 beforeEnter--> 解析异步路由组件 B --> 调用 B 的组件内路由守卫 beforeRouteEnter--> 调用全局路由解析守卫 beforeResolve--> 确认导航 --> 调用全局路由钩子 afterEach--> 渲染 B 组件 DOM
keep-alive
keep-alive 用于保留组件的渲染状态
不心愿组件被从新渲染影响用户体验和升高性能,而是心愿组件能够缓存下来, 维持以后的状态,这时候就能够用到 keep-alive
组件
(通常搭配生命周期 activated
应用)
keep-alive 是一个形象组件:它本身不会渲染一个 DOM 元素,也不会呈现在父组件链中;应用 keep-alive 包裹动静组件时,会缓存不流动的组件实例,而不是销毁它们。
Vuex
Vuex 是一个专为 Vue.js 利用程序开发的状态管理模式。它采纳集中式存储管理利用的所有组件的状态,并以相应的规定保障状态以一种可预测的形式发生变化。
简略来说就是:利用遇到多个组件共享状态时,应用 vuex。
vuex 的流程
graph TD
页面通过  mapAction  异步提交事件到  action-->action  通过  commit  把对应参数同步提交到  mutation-->mutation  批改  state  中对应的值 --> 通过  getter  传递对应值 --> 在页面的  computed  中通过  mapGetter  来动静获取  state  中的值
vuex 属性
mapAction:State , Getter , Mutation , Action , Module
- state:vuex 的根本数据(state),用来存储变量
- getter:从根本数据 (state) 派生的数据,相当于 state 的计算属性
- mutation:提交更新数据的办法,必须是同步的(如果须要异步应用 action)。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是咱们理论进行状态更改的中央,并且它会承受 state 作为第一个参数,提交载荷作为第二个参数。
- action:和 mutation 的性能大致相同
不同之处: - Action 提交的是 mutation,而不是间接变更状态
- Action 能够蕴含任意异步操作
-
modules:模块化 vuex,能够让每一个模块领有本人的 state、mutation、action、getters, 使得构造清晰,方便管理。
ajax 写在 methods 中还是 actions 中
- 仅在申请组件内应用:写在组件的 methods 中
- 在其余组件复用:写在 vuex 的 actions 中
(包装成 promise 返回,在调用处用 async await 解决返回的数据)