说说你对vue的理解
Vue中双向绑定的理解
侵入式就是没有调用任何函数,直接改变数据就能实现视图的变化。
非侵入式就是通过调用函数来改变数据就能实现视图的变化。
blog.csdn.net/weixin_4631…
- new Vue 先初始化,data 监听 响应化处理 过程发生在Oberver中
- 模版编译 找到动态绑定数据 data中拿到数据 初始化ui -> Compile
- 定义更新函数和watcher 当数据变化 watcher会调用更新函数
- data 一个key出现多次 Dep管家管理多个watcher
- data数据变化,找到Dep管家通知Watcher调用更新函数
SPA的理解
SPA(单页应用)首屏加载速度慢怎么解决
v-show 和 v-if 有什么区别
v-if和v-for不建议一起用?
Vue生命周期的理解
Vue实例挂载的过程中发生了什么
为什么Vue中的data属性是一个函数而不是一个对象?
Vue中给对象添加新属性时,界面不刷新怎么办?
Vue中组件和插件有什么区别?
Vue组件间通信方式都有哪些?
Vue中的$nextTick有什么作用?
说说你对vue的mixin的理解,以及有哪些应用场景?
Vue.observable是什么?
Vue 自定义指令
说说vue中,key的原理
说说你对Vue中 keep-alive 的理解
修饰符以及应用场景
虚拟DOM
虚拟DOM一定更快吗?
虚拟DOM/domDiff
我们常说的虚拟DOM是通过JS对象模拟出来的DOM节点,domDiff是通过特定算法计算出来一次操作所带来的DOM变化 react中涉及到虚拟DOM的代码主要分为以下三部分,其中核心是第二步的domDiff算法:
- 把render中的JSX(或者createElement这个API)转化成虚拟DOM
- 状态或属性改变后重新计算虚拟DOM并生成一个补丁对象(domDiff)
- 通过这个补丁对象更新视图中的DOM节点
虚拟DOM不一定更快
例如:一个页面就有一个按钮,点击一下,数字加一,那肯定是直接操作DOM更快。使用虚拟DOM无非白白增加了计算量和代码量。
那么为什么现在的框架都使用虚拟DOM呢?因为使用虚拟DOM可以提高代码的性能下限
,并极大的优化大量操作DOM时产生的性能损耗
。同时这些框架也保证了,即使在少数虚拟DOM不太给力的场景下,性能也在我们接受的范围内。
Diff
Vue3与Vue2的区别
Vue3.0的设计目标是什么?做了哪些优化?
Vue3.0 性能提升主要是通过哪几方面体现的?
Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?
Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同?
Vue 3.0中Treeshaking特性是什么,并举例进行说明?
对 Object.defineProperty 的理解
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
该方法接受三个参数,第一个参数是 obj:要定义属性的对象,第二个参数是 prop:要定义或修改的属性的名称或 Symbol,第三个参数是 descriptor:要定义或修改的属性描述符。
函数的第三个参数 descriptor 所表示的属性描述符有两种形式:数据描述符和存取描述
数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。
存取描述符是由 getter 函数和 setter 函数所描述的属性。
一个描述符只能是这两者其中之一;不能同时是两者。
这两种同时拥有下列两种键值:
- configurable:
是否可以删除目标属性
或是否可以再次修改属性的特性。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。 - enumerable:当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。默认为 false。
数据描述符
还具有以下可选键值:
- value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
- writable:当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。默认为 false。
const obj = {};
Object.defineProperty(obj, "property1", { value: 18 });
obj; // {'property1': 18}
obj.property1 = 24;
obj; // {'property1': 18} 因为默认writable为false
const obj = {};
Object.defineProperty(obj, "property1", { value: 18, writable: false });
obj.property1 = 24;
obj; // {'property1': 18}
// 改变状态
const obj = {};
Object.defineProperty(obj, "property1", { value: 18, writable: true });
obj.property1 = 24;
obj; // {'property1': 24}
存取描述符
还具有以下可选键值:
- get:属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的 this 并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。默认为 undefined。
- set:属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。默认为 undefined。
const obj = {};
Object.defineProperty(obj, "property1", {
get(value) {
return value;
},
set(newValue) {
value = newValue;
},
});
Vue2.x 与3.x 数据监听方面的区别:
在 Vue2.x 的版本中,双向绑定是基于 Object.defineProperty 方式实现的。而 Vue3.x 版本中,使用了 ES6 中的 Proxy 代理的方式实现。
Object.defineProperty(obj, prop, descriptor)
使用 Object.defineProperty 会产生三个主要的问题:
- 不能监听数组的变化
在 Vue2.x 中解决数组监听的方法是将能够改变原数组的方法进行重写实现(比如:push、 pop、shift、unshift、splice、sort、reverse),举例:
// 我们重写 push 方法
const originalPush = Array.prototype.push
Array.prototype.push = function() {
// 我们在这个位置就可以进行 数据劫持 了
console.log('数组被改变了')
originalPush.apply(this, arguments)
}
- 必须遍历对象的每个属性 可以通过 Object.keys() 来实现
- 必须深层遍历嵌套的对象 通过递归深层遍历嵌套对象,然后通过 Object.keys() 来实现对每个属性的劫持
Proxy
- Proxy 针对的整个对象,Object.defineProperty 针对单个属性,这就解决了 需要对对象进行深度递归(支持嵌套的复杂对象劫持)实现对每个属性劫持的问题
// 定义一个复杂对象
const obj = {
obj: {
children: {
a: 1
}
}
}
const objProxy = new Proxy(obj, {
get(target, property, receiver){
console.log('-- target --')
return Reflect.get(target, property, receiver)
},
set(target, property, value, receiver) {
console.log('-- set --')
return Reflect.set(target, property, value, receiver)
}
})
console.log(objProxy.obj) // 输出 '-- target --'
console.log(objProxy.a = 2) // 输出 '-- set --'
- Proxy 解决了 Object.defineProperty 无法劫持数组的问题
const ary = [1, 2, 3]
const aryProxy = new Proxy(ary, {
get(target, property, receiver){
console.log('-- target --')
return Reflect.get(target, property, receiver)
},
set(target, property, value, receiver) {
console.log('-- set --')
return Reflect.set(target, property, value, receiver)
}
})
console.log(aryProxy[0]) // 输出 '-- target --'
console.log(aryProxy.push(1)) // 输出 '-- set --'
- 比 Object.defineProperty 有更多的拦截方法,对比一些新的浏览器,可能会对 Proxy 针正对性的优化,有助于性能提升