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 LRVue.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
[elis] 在 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 解决返回的数据)