基础:
v-if和v-show 区别:
v-show:通过display来控制显示和隐藏;
v-if是组件真正的渲染和销毁,而不是现实和吟唱;
频繁切换场景使用v-show;
keep-alive:
缓存组件,需要频繁切换但不需要频繁渲染常用;例如tab切换;
也可以作为vue性能优化手段之一;
mixin:
优点:适用于 多个组件有相同的逻辑,可以使用mixin,比较方便;
缺点:多mixin可能造成命名冲突;变量来源不明确,不利于阅读;
mixin和组件可能出现多对多关系,复杂度比较高;
computed 和watch区别
computed优点:缓存,data不变不会重新计算;
提升性能;
$nextTick:
$nextTick在Dom更新完成之后,触发回调;
实现原理:
nextTick 方法主要是使用了宏任务和微任务,定义了一个异步方法.多次调用 nextTick 会将方法存入 队列中,通过这个异步方法清空当前队列。 所以这个 nextTick 方法就是异步方法;
在下次 DOM 更新循环结束之后执行延迟回调。nextTick主要使用了宏任务和微任务。根据执行环境分别尝试采用
- Promise
- MutationObserver
- setImmediate
- 如果以上都不行则采用setTimeout
创建并返回一个新的 MutationObserver 它会在指定的DOM发生变化时被调用。
setImmediate()方法用于中断长时间运行的操作,并在浏览器完成其他操作(如事件和显示更新)后立即运行回调函数。
定义了一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空当前队列。
v-for中用key:
1)必须是key,不能是index;
2)diff算法中通过tag和key来判断,是不是sameNode;
key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速
- 更准确:因为带 key 就不是就地复用了,在 sameNode 函数a.key === b.key对比中可以避免就地复用的情况。所以会更加准确。
- 更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快
3)减少渲染次数,提升性能;
vue中常用的组件通讯;
常用的:
父子组件: props和 this.$emit;
自定义事件: event.off 和 event.off)
vuex
总共大致有这几种:
父子组件通信
- 事件机制(**父->子props,子->父 emit)
- 获取父子组件实例 children
- Ref 获取实例的方式调用组件的属性或者方法
- Provide、inject (不推荐使用,组件库时很常用)
兄弟组件通信
- eventBus 这种方法通过一个空的 Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件;
Vue.prototype.$bus = new Vue
- Vuex
跨级组件通信
-
Vuex
-
listeners
beforeDetory 使用场景:
解除自定义事件evenet.$off
清楚定时器
解除自定义DOM 事件,例如window scroll等等;
自己理解(小白,若有不当敬请指出):
vue如何监听数据变化?响应式原理
核心就是Object.defineProperty来实现响应式(当然vue3.0使用的是Proxy)
大致分为 监听对象情况, 需要深度监听复杂对象(observer(value))情况,监听数组这几种情况;
监听对象核心:
function defineReactive(target,key,value) {
// 核心 api
//深度监听
observer(value)
Object.defineProperty(target,key, {
get() {
return value
},
set(newValue) {
if(newValue !== value) {
//深度监听新值
observer(newValue)
// 设置新值
value = newValue
// 触发更新视图
updateView()
}
}
})}
复制代码
需要深度监听复杂对象(observer(value))情况
//如果是复杂对象,需要调用obser方法// 监听对象
function oberver(target) {
if (typeof target !== 'object' || target === null) {
// 不是对象 或数组
return target }
// 污染全局的Array 原型
if(Array.isArray(target)) {
target._proto_ = arrProto }
// 重新定义各个属性
for (let key in target) {
defineReactive(target,key,target[key])
}}
复制代码
监听数组变化:(无法原生监听到数组,需要此处特殊处理;)
// 重新定义数组原型
const oldArrayProperty = Array.prototype
// 创建新对象,原型指向 oldArrayProperty ,再扩展新的方法不会影响原型
const arrProto = Object.create(oldArrayProperty);
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(methodName => {
arrProto[methodName] = function () {
updateView() // 触发视图更新
oldArrayProperty[methodName].call(this, ...arguments)
// Array.prototype.push.call(this, ...arguments)
}
})
复制代码
object.defineProperty 缺点:
1)深度监听,需要递归到底(源数据对象有多深,就要一次性递循环归到最深处),一次性计算量比较大
2)无法监听新增属性/删除属性(可以通过Vue.set Vue.delete增删)
3)无法原生监听到数组,需要特殊处理;
diff 算法过程:
这个我是看博客看了几篇,还是没明白;后来花了快一天时间才明白;建议自己手本子上画diff比对过程;
diff算法时间复杂度
Object.defineproperty原理
虚拟dom
vue 生命周期
V3.0新特性
vue 和 react 对比;