vue 面试题
2023-05-20 本文已影响0人
宏_4491
vue的响应式原理
Vue的响应式原理是基于Object.defineProperty()实现的。在Vue中,每一个组件实例都有一个对应的vm实例,其中的data对象就是Vue中的响应式数据。当我们修改这些数据时,会触发视图的自动更新。
Vue实现响应式原理的具体步骤如下:
在初始化时,对data对象进行递归遍历,使用Object.defineProperty()将每个属性转换为getter/setter。
每当访问该属性时,会将当前的Watcher对象(用于存储依赖和更新DOM)添加到该属性的依赖列表中。
当属性的值被修改时,会触发setter函数,setter函数会通知所有依赖于该属性的Watcher对象进行更新操作。
在更新操作中,Watcher对象会重新计算属性值,并将新值与旧值进行比较,如果发现两个值不相等,则会执行更新操作,更新视图中与该属性相关的部分。
通过以上过程,Vue实现了数据与视图之间的绑定,当数据发生变化时,视图会自动更新,从而实现了响应式的效果。
vue3响应式原理
ue3的响应式原理与Vue2相比有所改进,主要是采用了ES6的Proxy来实现响应式。
具体实现如下:
在初始化组件时,创建一个原始数据对象raw,并使用Proxy对其进行代理。
当通过raw对象访问或者修改数据时,会触发Proxy中的get和set函数。
在get函数中,依然需要进行依赖收集,因此需要创建一个新的effect对象来存储当前的依赖。
在set函数中,触发所有有关联的效果(effect)进行更新。同时,为保证性能优化,Vue3还引入了缓存机制(WeakMap)来避免重复触发更新操作。
对于响应式数据的嵌套对象和数组等,Vue3同样可以进行代理,并且在修改内部属性时,也会触发外部数据的更新。
Vue3使用Proxy来代理数据对象,利用Proxy的特性可以监听对象的任何属性的变化,不像Object.defineProperty只能监听对象某个属性的变化,
从而提高了Vue3的响应速度和性能。同时,Vue3还推出了Composition API,使得组件逻辑更加清晰,易于维护和管理。
Vue中的v-if和v-show都用于控制组件或元素的显示和隐藏,但是有一些区别。
v-if是“真正”的条件渲染,当条件为false时,组件或元素根本就不会被渲染到页面上;而v-show只是切换了元素的CSS样式display属性,当条件为false时,它依然存在于DOM结构中。
v-if的切换有比较高的代价,因为它会重新创建或销毁组件和子组件;而v-show只是改变了样式,所以切换的代价较小。
v-if是惰性的,只有在条件为true时才会进行渲染,可以节约资源和提高初始化速度;而v-show在任何情况下都会被渲染,不利于性能优化。
使用时需要注意:
在需要频繁切换的元素上使用v-show,因为它的切换代价较小;在只需要一次性渲染的元素上使用v-if,因为它会占用更多内存和CPU资源。
尽量避免在template标签上使用v-if、v-show,因为template标签本身并没有实际的渲染,并且在某些情况下可能会造成不必要的性能损耗。
在同时需要使用v-if和v-for时,应该让v-for先渲染,因为v-if会比v-for的性能开销更大。
总之,在使用v-if和v-show时,应该根据实际情况来选择,以达到最优的性能表现。
$refs在通讯时有什么弊端
使用$refs进行通讯的弊端主要有以下几点:
破坏了单向数据流的原则:在Vue中,数据应该是单向流动的,即从父组件向子组件流动。使用$refs通信时会破坏这种单向数据流的原则,因为父组件可以直接修改子组件中的数据,容易导致状态管理的混乱和难以维护。
引起脆弱的组件关系:使用$refs通信时,父组件和子组件之间形成了紧密的耦合关系,这使得组件变得更加脆弱,如果其中一个组件发生了变化,则可能导致另一个组件无法正常工作。
可能导致组件复用困难:在Vue中,组件是可以复用的。但是,如果使用$refs进行通信,则只能将父组件和子组件绑定在一起,不能实现真正的组件复用。
vue的修饰符
以下是Vue中常用的修饰符:
.prevent:阻止默认事件的发生,相当于调用event.preventDefault()方法。
.stop:阻止事件冒泡,相当于调用event.stopPropagation()方法。
.capture:添加事件监听器时使用事件捕获模式,默认是事件冒泡模式。
.self:只有事件在该元素本身触发时才调用监听器,不包括子元素。
.once:事件只触发一次,即监听器只调用一次。
.passive:表示事件不会调用event.preventDefault()方法,可以提高移动端滚动性能。
.native:使用该修饰符可以监听组件根元素上的原生事件。
.sync:用于父组件与子组件之间进行双向数据绑定,使得父组件的变化可以传递给子组件,子组件的变化也可以反向传递给父组件。
vue 父子组件嵌套下的生命周期顺序
便于记忆的口诀
创建前,创建中, 渲染前,更新前 都从父到子组件
渲染中,更新中,销毁前和销毁中 都是子到父组件
父组件beforeCreate钩子函数被触发。
父组件created钩子函数被触发,此时父组件的数据已经初始化完成。
父组件beforeMount钩子函数被触发。
子组件beforeCreate钩子函数被触发。
子组件created钩子函数被触发,此时子组件的数据已经初始化完成。
子组件beforeMount钩子函数被触发。
子组件mounted钩子函数被触发,此时子组件已经被挂载到DOM中。
父组件mounted钩子函数被触发,此时父组件也已经被挂载到DOM中。
父组件beforeUpdate钩子函数被触发。
子组件beforeUpdate钩子函数被触发。
子组件updated钩子函数被触发,此时子组件已经更新完成。
父组件updated钩子函数被触发,此时父组件也已经更新完成。
当组件被销毁时,会先触发子组件的beforeDestroy钩子函数,然后是父组件的beforeDestroy钩子函数。
最后,先销毁子组件,再销毁父组件。子组件destroyed钩子函数被触发,然后是父组件destroyed钩子函数被触发。
Vue中的computed和watch有什么区别?
1、监听的数据不同:
computed监听的是由 Vue 实例中已有的数据计算而来的新数据,称作计算属性。可以通过getter方法来获取这个新数据,每次getter方法执行时,都会检测它所依赖的原有数据是否发生变化,只有在新旧值不同时才会重新计算。
watch监听的是某个指定的响应式数据,当该数据发生变化时就会触发回调函数,可以在回调函数中执行一些额外的代码,例如Ajax请求等。watch 的回调函数接收两个参数:新值和旧值。
2、执行时机和方式不同:
computed 是在模板渲染时计算的。如果 computed 依赖的属性没有发生变化,就不会重复计算。而且 computed 计算出的值会被缓存起来,除非依赖的属性发生了改变,否则下次访问这个计算属性时会直接从缓存中返回结果。
watch 则是在监听到指定的数据发生变化时异步执行回调函数。因此 watch 执行的时机是视图更新之后。也就是说,无论数据是否有变化,watch 都会被触发。
综上所述,computed 适合计算属性值并缓存结果,从而减少重复计算。而 watch 适合执行异步或开销较大的操作。当数据变化时需要立即响应并采取一些行动时,watch 是更好的选择。
vue ref 和 reactive 的区别
功能不同
ref 是 Vue 3 中新增的一种数据绑定方式,用于在模板或者 JavaScript 代码中获取组件或标签的引用。通过 ref,在 Vue 组件中可以访问到在 HTML 模板中定义的元素或组件实例,并对其进行操作。ref 可以用于访问 DOM 元素、组件实例以及其他任何 Vue 实例的实例变量。
reactive 是 Vue 2 和 Vue 3 中都支持的一个数据绑定方式,用于监听数据的变化并重新渲染视图。通过 reactive,可以将普通 JavaScript 对象转换成响应式对象,当响应式对象的属性值发生变化时,Vue 会自动更新视图,以反映最新的状态。
使用方式不同
ref 主要用于获取组件或标签的引用,一般会使用 .value 属性来访问 ref 引用的实例变量。例如,在模板中使用 ref 获取一个 input 元素的引用:
<template>
<input type="text" ref="inputRef" />
</template>
<script>
export default {
mounted() {
this.$refs.inputRef.value = 'Hello World';
},
};
</script>
reactive 则主要用于监测数据的变化,需要调用 Vue 提供的 reactive 函数将数据转换成响应式对象。例如,在 Vue 中使用 reactive 监测一个状态变量:
<template>
<div>{{ count }}</div>
</template>
<script>
import { reactive } from 'vue';
export default {
setup() {
const state = reactive({
count: 0,
});
setInterval(() => {
state.count++;
}, 1000);
return {
count: state.count,
};
},
};
</script>
在上面的代码中,使用 reactive 函数将 count 变量转换成响应式对象,并通过 setup 函数返回一个包含 count 变量的对象,以便在模板中使用。
综上所述,ref 和 reactive 都是 Vue 中的重要特性,但它们的功能和使用方式不同,需要根据具体的场景来选择使用哪一种特性。