可以,但是尽量不要同时使用,v-for计算优先级比v-if高,首先会把虚拟节点渲染出来,然后再进行v-if判断。降低渲染性能
如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。key 是为 Vue 中 vnode 的唯一标记,通过这个 key,diff 算法可以更准确、更快速
key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快当事件没有参数,则默认有个 event 参数;如果有自定义参数,则需要使用$event 传过去。
event 的构造函数是 MouseEvent,即是原生的 event 对象event 被挂载到当前元素下,即 event.targetprops接收,可以使用数组/对象数据结构,对象结构可以定义类型和默认值。$emit 事件回传js 文件,其中声明一个 Vue 实例即可$on,$emit,$off,参数分别是:注册函数名,真实函数beforeDestroy 中调用$offbeforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mountedbeforeUpdate -> 子beforeUpdate -> 子updated -> 父updatedbeforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyedbeforeCreate -> created -> beforeMount -> mounted -> beforeUpdate -> updated -> beforeDestroy -> destroyed采用数据劫持结合观察者模式的方式
通过 Object.defineProperty()来劫持各个属性(只会劫持已经存在的属性)的 setter,getter,dep 和 Watcher 实现依赖收集和派发更新的过程:
vue 将 data 初始化为一个 Observer 并对对象中的每个值,重写了其中的 get、set,data 中的每个 key,都有一个独立的 dep(依赖收集器)。get 中,向 dep(依赖收集器)添加了监听mount 时,实例了一个 Watcher,将收集器的目标指向了当前 Watcherdata 值发生变更时,触发 set,触发了 dep(依赖收集器)中的所有监听的更新,来触发 Watcher.updatenextTick 中的回调是在下次 DOM 更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。主要思路就是采用微任务优先的方式调用异步方法去执行 nextTick 包装的方法
vuex 是专门为 vue 提供的全局状态管理系统,用于多个组件中数据共享、数据缓存等。(无法持久化、内部核心原理是通过创造一个全局实例 new Vue)
主要包括以下几个模块:
Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。store 中状态的方法,且必须是同步函数。mutation,而不是直接变更状态,可以包含任意异步操作。Store 拆分为多个 store 且同时保存在单一的状态树中。作用与用法:
开发中缓存组件使用 keep-alive 组件,keep-alive 是 vue 内置组件,keep-alive 包裹动态组件 component 时,会缓存不活动的组件实例,而不是销毁它们,这样在组件切换过程中将状态保留在内存中,防止重复渲染 DOM。
使用细节:
结合属性 include 和 exclude 可以明确指定缓存哪些组件或排除缓存指定组件。vue3 中结合 vue-router 时变化较大,之前是 keep-alive 包裹 router-view,现在需要反过来用 router-view 包裹 keep-alive。
keep-alive 的中缓存的时候还运用了 LRU(Least Recently Used) 算法。
LRU(最近最少使用) 缓存机制:
如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1。如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间
组件缓存后更新,解决方案可以有以下两种:
vue-router 的项目,每次进入路由的时候,都会执行 beforeRouteEnter。keep-alive 缓存的组件被激活的时候,都会执行 activated 钩子。原理:
keep-alive 是一个通用组件,它内部定义了一个 map,缓存创建过的组件实例,它返回的渲染函数内部会查找内嵌的 component 组件对应组件的 vnode,如果该组件在 map 中存在就直接返回它。由于 component 的 is 属性是个响应式数据,因此只要它变化,keep-alive 的 render 函数就会重新执行。
参数:
keep-alive 接收三个参数:
include 和 exclude,传数组情况居多。
生命周期:
生命周期有:activated 激活、deactivated 离开
当再次前进或者后退的时候只触发 activated。
使用 keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来 created 钩子中获取数据的任务。那么,我们一般会在动态组件、路由组件去用到 keep-alive 组件。
hash 模式
URL 中 # 后面的东西 它的特点在于:hash 虽然出现 URL 中,但不会被包含在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。hash 的改变添加监听事件window.addEventListener("hashchange", funcRef, false); 每一次改变 hash(window.location.hash),都会在浏览器的访问历史中增加一个记录。
利用 hash 的以上特点,就可以来实现前端路由 “更新视图但不重新请求页面” 的功能了
特点:兼容性好但是不美观
history 模式
利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。
这两个方法应用于浏览器的历史记录站,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。这两个方法有个共同的特点:当调用他们修改浏览器历史记录栈后,虽然当前 URL 改变了,但浏览器不会刷新页面,这就为单页应用前端路由 “更新视图但不重新请求页面” 提供了基础。
特点:虽然美观,但是刷新会出现 404 需要后端进行配置
1.工厂模式 - 传入参数即可创建实例
虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode
2.单例模式 - 整个程序有且仅有一个实例
vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉
3.观察者模式 (响应式数据原理)
4.策略模式 策略模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案-比如选项的合并策略
5.策略模式:优化 if else 冗余代码
6.代理模式:mini-vue proxy
$on、$emit 基于发布订阅模式$on 用来收集所有的事件依赖,他会将传入的参数 event 和 fn 作为 key 和 value 的形式存到 vm._events 这个事件集合里,就像这样 vm._events[event]=[fn];$emit 是用来触发事件的,他会根据传入的 event 在 vm_events 中找到对应的事件并执行 invokeWithErrorHandling(cbs[i], vm, args, vm, info)invokeWithErrorHandling 方法可以发现,他是通过 handler.apply(context, args) 和 handler.call(context) 的形式执行对应的方法用 js 模拟一颗 dom 树,放在浏览器内存中.当你要变更时,虚拟 dom 使用 diff 算法进行新旧虚拟 dom 的比较,将变更放到变更队列中,反应到实际的 dom 树,减少了 dom 操作。
虚拟 DOM 将 DOM 树转换成一个 JS 对象树,diff 算法逐层比较,删除,添加操作,但是,如果有多个相同的元素,可能会浪费性能,所以,react 和 vue-for 引入 key 值进行区分。
优点:
缺点:
无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。
首次渲染大量 DOM 时,由于多了一层虚拟 DOM 的计算,会比 innerHTML 插入慢。
组件和组件之间有时候会存在相同的代码逻辑,分为局部混入和全局混入,我们希望对相同的代码逻辑进行抽取
缺点:
Vue3 使用 Composition API 替代了,优点:
Vue 自定义指令有全局注册和局部注册两种方式。先来看看注册全局指令的方式,通过 Vue.directive(id, [definition]) 方式注册全局指令。然后在入口文件中进行 Vue.use() 调用。
它的作用价值在于当开发人员在某些场景下需要对普通 DOM 元素进行操作。提高代码复用。
指令本质上是装饰器,是 vue 对 HTML 元素的扩展,给 HTML 元素增加自定义功能。vue 编译 DOM 时,会找到指令对象,执行指令的相关方法。
自定义指令有五个生命周期(也叫钩子函数),分别是 bind、inserted、update、componentUpdated、unbind
原理
$on、$emit 是基于发布订阅模式的,维护一个事件中心,on 的时候将事件按名称存在事件中心里,称之为订阅者,然后 emit 将对应的事件进行发布,去执行事件中心里的对应的监听器
因为响应式数据 我们给对象和数组本身都增加了 __ob__ 属性,代表的是 Observer 实例。当给对象新增不存在的属性 首先会把新的属性进行响应式跟踪 然后会触发对象 __ob__ 的 dep 收集到的 watcher 去更新,当修改数组索引时我们调用数组本身的 splice 方法去更新数组
setup 相当于整合了 beforeCreate 和 createdsetup 中的函数:如何选择?
ref:
.value 修改值toRef:
toRefs:
.value 属性的 get 和 set 实现响应式.value,其他情况都需要emitsoptions 父组件的绑定事件setup 整合 beforeCreate 和 created``,beforeDestroy 改为 beforeUnmount,destroyed 改为 unmounted,其他与 vue2 一致.syncdefineAsyncComponent,使用这个函数包裹 import() 引入异步组件loading,主要实现原理就是具名插槽