Vue组件data为什么必须是个函数?
- 每次使用组件时都会对组件进行实例化操作,并且调用data函数返回一个对象作为组件的数据源。这样可以保证多个组件间数据互不影响
nextTick在哪里使用?原理是?
nextTick中的回调是在下次 DOM 更新循环结束之后执行的延迟回调。可用于获取更新后的 DOM。Vue中数据更新是异步的,使用nextTick方法可以保证用户定义的逻辑在更新之后执行。
computed和watch区别
- computed和watch都是基于Watcher来实现的
- computed属性是具备缓存的,依赖的值不发生变化,对其取值时计算属性方法不会重新执行
- watch则是监控值的变化,当值发生变化时调用对应的回调函数
Vue.set方法是如何实现的
- 我们给对象和数组本身都增加了dep属性
- 当给对象新增不存在的属性则触发对象依赖的watcher去更新
- 当修改数组索引时我们调用数组本身的splice方法去更新数组
Vue为什么需要虚拟DOM
- 由于直接操作DOM性能低但是js层的操作效率高,可以将DOM操作转化成对象操作,最终通过diff算法比对差异进行更新DOM(减少了对真实DOM的操作)。
- 虚拟DOM不依赖真实平台环境从而也可以实现跨平台。
Vue中diff算法原理
- Vue的diff算法是平级比较,不考虑跨级比较的情况。内部采用深度递归的方式 + 双指针的方式进行比较。
- 1.先比较是否是相同节点 key tag
- 2.相同节点比较属性,并复用老节点
- 3.比较儿子节点,考虑老节点和新节点儿子的情况
- 4.优化比较:头头、尾尾、头尾、尾头
- 5.比对查找进行复用
- Vue3中采用最长递增子序列来实现diff优化
请说明Vue中key的作用和原理,谈谈你对它的理解
- Vue在patch过程中通过key可以判断两个虚拟节点是否是相同节点。(可以复用老节点)
- 无key会导致更新的时候出问题
- 尽量不要采用索引作为key
Vue的生命周期方法有哪些?一般在哪一步发送请求及原因
beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/
watcher事件配置之前被调用。
created 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。这里没有
e
l
b
e
f
o
r
e
M
o
u
n
t
在
挂
载
开
始
之
前
被
调
用
:
相
关
的
r
e
n
d
e
r
函
数
首
次
被
调
用
。
m
o
u
n
t
e
d
e
l
被
新
创
建
的
v
m
.
el beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。 mounted el 被新创建的 vm.
elbeforeMount在挂载开始之前被调用:相关的render函数首次被调用。mountedel被新创建的vm.el 替换,并挂载到实例上去之后调用该钩子。
beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
keep-alive (activated 和 deactivated)
JS数组去重的几种常见方法
最简单数组去重法
- 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中
- IE8以下不支持数组的indexOf方法
function uniq(array){
var temp = []; //一个新的临时数组
for(var i = 0; i < array.length; i++){
if(temp.indexOf(array[i]) == -1){
temp.push(array[i]);
}
}
return temp;
}
var aa = [1,2,2,4,9,6,7,5,2,3,5,6,5];
console.log(uniq(aa))
对象键值法去重
- 速度最快, 占空间最多(空间换时间)
- 该方法执行的速度比其他任何方法都快, 就是占用的内存大一些。
- 现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键,
- 不是的话给对象新增该键并放入新数组。
- 注意点:判断是否为js对象键时,会自动对传入的键执行“toString()”,
- 不同的键可能会被误认为一样,例如n[val]-- n[1]、n[“1”];
- 解决上述问题还是得调用“indexOf”。
function uniq(array){
var temp = {}, r = [], len = array.length, val, type;
for (var i = 0; i < len; i++) {
val = array[i];
type = typeof val;
if (!temp[val]) {
temp[val] = [type];
r.push(val);
} else if (temp[val].indexOf(type) < 0) {
temp[val].push(type);
r.push(val);
}
}
return r;
}
var aa = [1,2,"2",4,9,"a","a",2,3,5,6,5];
console.log(uniq(aa));
优化遍历数组法
思路:获取没重复的最右一值放入新数组(检测到有重复值时终止当前循环同时进入顶层循环的下一轮判断)
function uniq(array){
var temp = [];
var index = [];
var l = array.length;
for(var i = 0; i < l; i++) {
for(var j = i + 1; j < l; j++){
if (array[i] === array[j]){
i++;
j = i;
}
}
temp.push(array[i]);
index.push(i);
}
console.log(index);
return temp;
}
var aa = [1,2,2,3,5,3,6,5];
console.log(uniq(aa));
1.调用render方法产生虚拟节点 虚拟DOM
2.根据虚拟DOM产生真实DOM
vue核心流程 :① 创造了响应式数据,②模板转换成ast语法树 ;
render函数会去产生虚拟节点(使用响应式数据根据生成的虚拟节点创造真实的DOM)
// h() _c()
export function createElementVNode(vm, tag, data, ...children) {
if (data == null) {
data = {}
}
let key = data.key;
if (key) {
delete data.key
}
return vnode(vm, tag, key, data, children);
}
// _v();
export function createTextVNode(vm, text) {
return vnode(vm, undefined, undefined, undefined, undefined,
text);
}
// ast一样吗?ast做的是语法层面的转化 他描述的是语法本身
(可以描述js css html)
// 我们的虚拟dom 是描述的dom元素,可以增加一些自定义属性 (描述dom的)
function vnode(vm, tag, key, data, children, text) {
return {
vm,
tag,
key,
data,
children,
text
// ....
}
}