Open krislee94 opened 1 year ago
介绍一下Vue 2和Vue 3的主要区别和改进之处。
Vue 3的Composition API是什么?它与Vue 2的Options API有什么不同?
在Vue 2中,使用Options API来定义组件。Options API是一种以对象形式传递选项的方式,通过在组件的对象中定义不同的选项(如data、methods、computed、watch等)来描述组件的属性、方法和响应式数据等。
在Vue 3中,Composition API 提供了更加灵活、模块化和可组合的方式来编写组件的逻辑。开发者可以将相关的逻辑组织成composables(可组合的函数),每个composable都封装了一部分逻辑,并可以在组件中进行复用。
什么是响应式数据,在Vue中如何实现响应式数据?
// Vue 2的响应式数据实现
class Vue {
constructor(options) {
this._data = options.data;
this._observer = observe(this._data);
// ...
}
}
function observe(obj) {
if (typeof obj !== 'object' || obj === null) {
return;
}
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key]);
});
}
function defineReactive(obj, key, val) {
observe(val); // 递归劫持子属性
const dep = new Dep(); // 创建一个依赖对象
Object.defineProperty(obj, key, {
get() {
// 添加当前Watcher到依赖列表中
if (Dep.target) {
dep.addWatcher(Dep.target);
}
return val;
},
set(newVal) {
if (newVal === val) {
return;
}
val = newVal;
// 依赖发生变化时,通知依赖的Watcher进行更新
dep.notify();
}
});
}
class Dep {
constructor() {
this.watchers = [];
}
addWatcher(watcher) {
this.watchers.push(watcher);
}
notify() {
this.watchers.forEach(watcher => watcher.update());
}
}
// 创建一个Vue实例
const vm = new Vue({
data: {
message: 'Hello Vue'
}
});
在Vue3中,响应式数据的视线采用了Proxy对象。并且将Observer和Watcher概念合并成为了一个新的Reactivity模块。
// Vue 3的响应式数据实现
class Vue {
constructor(options) {
this._data = options.data;
this._proxy = reactive(this._data);
// ...
}
}
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
// Track:追踪依赖
track(target, key);
return Reflect.get(target, key);
},
set(target, key, value) {
const oldValue = target[key];
// Trigger:触发更新
const result = Reflect.set(target, key, value);
if (oldValue !== value) {
trigger(target, key);
}
return result;
}
});
}
function track(target, key) {
// 添加依赖
const effect = activeEffectStack[activeEffectStack.length - 1];
if (effect) {
let depsMap = targetMap.get(target);
if (!depsMap) {
depsMap = new Map();
targetMap.set(target, depsMap);
}
let dep = depsMap.get(key);
if (!dep) {
dep = new Set();
depsMap.set(key, dep);
}
if (!dep.has(effect)) {
dep.add(effect);
effect.deps.push(dep);
}
}
}
function trigger(target, key) {
// 触发更新
const depsMap = targetMap.get(target);
if (!depsMap) {
return;
}
const dep = depsMap.get(key);
if (!dep) {
return;
}
dep.forEach(effect => {
effect();
});
}
class Effect {
constructor(fn) {
this.fn = fn;
this.deps = [];
}
update() {
// 重新执行
this.fn();
}
run() {
// 追踪依赖
activeEffectStack.push(this);
this.fn();
activeEffectStack.pop();
}
}
const targetMap = new WeakMap();
const activeEffectStack = [];
// 创建一个Vue实例
const vm = new Vue({
data: {
message: 'Hello Vue'
}
});
Vue 2中的v-bind和v-model指令有什么作用?Vue 3中是否有类似的指令?
有的。在Vue 2和Vue 3中,v-bind和v-model指令的作用是相同的,并且在Vue 3中v-bind指令可以使用简写语法。
Vue 2和Vue 3中的虚拟DOM是如何工作的?有哪些优化措施?
Vue 2和Vue 3都使用虚拟DOM来优化页面的渲染性能,其工作原理类似,通过对比差异来减少DOM操作的数量。同时,Vue 3还引入了一些新的优化措施,如批量异步更新、静态标记、编译优化和长列表优化等,进一步提升了性能和用户体验。
先大概说说虚拟dom
差别
什么是Vue Router?请解释一下Vue 2和Vue 3中的路由配置和导航守卫的不同之处。
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home
},
// ...
]
})
这种方式基本上没有变化,仍然适用于Vue 3中的vue-router。
同时Vue3使用createRouter
const router = createRouter({
routes: [
{
path: '/home',
component: Home
},
// ...
]
})
beforeEach 、afterEach 保持不变。 beforeEnter --> beforeRouteEnter , beforeRouteUpdate.新增导航守卫函数用户当前路由复用的时候执行逻辑、beforeRouteLeave组件离开的时候执行。 beforeRouteUpdate和beforeRouteLeave函数。这些变化使得Vue 3的路由配置和导航守卫更加灵活和强大。
在Vue 2和Vue 3中如何使用Vuex进行状态管理?是否有任何改进或新特性?
vue2中使用Vuex.Store. Vue3中,使用createStore. 同时Vue3中更推荐使用Pinia。 想比vuex中更精简。
Vue 3中的推导式props(Props Composition)是什么?它与Vue 2中的props有什么不同?
Vue3推导式的props是一种新的特性,用于根据组件的上下文推导出props的默认值,它可以显著简化组件的props的配置,提高代码的可读性和可维护性。
vue2中需要通过声明props并指定默认值来定义组件的props。这种方式有时候会使得组件的props声明变得冗长。特别是当props的默认值依赖于其他props或计算属性时。
Vue 3中的推导式props提供了一种更简洁的方式来定义props的默认值。它允许我们在props配置中使用JavaScript表达式,并在运行时根据组件的上下文来推导出props的默认值。
vue2写法:
props: {
count: {
type: Number,
default: function () {
return this.initialCount * 2
}
}
},
vue3写法
const props = defineProps({
count:{
type:number,
default: ()=> initialCount * 2
}
})
Vue 2和Vue 3中的异步组件(Async Components)是如何工作的?有什么优点?
在Vue 2和Vue 3中,异步组件是一种延迟加载的组件,它们在需要时才会被加载和渲染,而不是在初始加载时就被包含在应用程序中。
Vue3
import { defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'))
Vue2
Vue.component('AsyncComponent', (resolve) => {
import('./AsyncComponent.vue').then((module) => {
resolve(module.default)
})
})
具体使用参考:https://cn.vuejs.org/guide/components/async.html
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/MyComponent.vue')
)
const AsyncComp = defineAsyncComponent({
// 加载函数
loader: () => import('./Foo.vue'),
// 加载异步组件时使用的组件
loadingComponent: LoadingComponent,
// 展示加载组件前的延迟时间,默认为 200ms
delay: 200,
// 加载失败后展示的组件
errorComponent: ErrorComponent,
// 如果提供了一个 timeout 时间限制,并超时了
// 也会显示这里配置的报错组件,默认值是:Infinity
timeout: 3000
})
搭配 Suspense 使用
<Suspense>
└─ <Dashboard>
├─ <Profile>
│ └─ <FriendStatus>(组件有异步的 setup())
└─ <Content>
├─ <ActivityFeed> (异步组件)
└─ <Stats>(异步组件)
在这个组件树中有多个嵌套组件,要渲染出它们,首先得解析一些异步资源。如果没有
在Vue 3中,什么是Teleport(瞬移)?有什么用途和优势?
在Vue 3中,Teleport(瞬移)是一种新特性,它允许我们将一个组件的内容在DOM中的任意位置进行渲染,而不受组件的嵌套层级限制。简单来说,Teleport可以将组件的内容“瞬移”到指定的目标位置。
Teleport通过
<teleport to="#target">
<!-- 组件内容 -->
</teleport>
Teleport有以下几个主要用途和优势:
提供更灵活的布局控制:Teleport能够将组件的内容渲染到DOM中的任意位置,不受组件嵌套层级的限制。这使得我们能够更精确地控制组件在页面中的布局,并实现更高级的布局效果。
解决组件插槽限制:在Vue 2中,插槽(slot)在组件嵌套层级中有一定的限制,父组件无法将内容插入到子组件的任意位置。而使用Teleport,我们可以轻松地将内容瞬移到子组件内的任意位置。
模态框和弹出窗口:Teleport非常适合用于创建模态框和弹出窗口等需要将组件的内容渲染到页面上特定位置的场景。通过使用Teleport,我们可以方便地将这些组件的内容渲染到
内的某个位置,从而实现浮动弹出窗口的效果。改善CSS层叠和样式控制:使用Teleport可以将组件的内容渲染到页面的某个位置,这可以避免嵌套层级带来的CSS层叠和样式控制问题。我们可以在目标位置上直接应用样式,而不必考虑组件嵌套层级的影响。
Vue 3中实现服务端渲染(SSR)?
创建一个Vue应用实例,并将其导出。
创建一个服务端入口文件,用于处理服务端请求并渲染Vue应用。
在服务端入口文件中,使用createRenderer创建一个新的渲染器。
在服务端入口文件中,使用renderToString或者renderToStream方法来将Vue应用实例渲染成HTML字符串或流。
配置服务端打包的构建脚本,将Vue应用打包成一个用于服务端渲染的bundle文件。
在服务器中启动一个Node.js实例,并将请求交给服务端入口文件处理。
Vue 2和Vue 3中的动态组件(Dynamic Components)如何使用?有什么不同之处?
在Vue 2中,你可以使用Vue的内置指令
<template>
<div>
<button @click="activeComponent = 'ComponentA'">Component A</button>
<button @click="activeComponent = 'ComponentB'">Component B</button>
<component :is="activeComponent"></component>
</div>
</template>
<script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
export default {
components: {
ComponentA,
ComponentB
},
data() {
return {
activeComponent: ''
};
}
};
</script>
而在vue3中。
在Vue 3中,使用动态组件的方式略有不同。Vue 3引入了一个新的内置组件
请解释Vue 2和Vue 3中的key属性的作用和用法。
在Vue中,key属性是用于帮助Vue识别和跟踪与每个VNode(虚拟节点)相关的元素的唯一身份标识。它的作用是在Vue进行重新渲染时,能够准确地确定哪些元素需要被更新、重用或移除。
什么是Vue Test Utils?你在写Vue组件单元测试时会用到哪些工具和方法?
Vue Test Utils是一个官方提供的用于测试Vue组件的工具库,它提供了一组用于创建、操作和断言Vue组件行为的API。
在编写Vue组件的单元测试时,我通常会使用以下工具和方法:
mount:用于挂载Vue组件,返回一个包装器对象,可以用于访问和操作组件实例。 shallowMount:类似于mount,但是只渲染组件的当前级别,而不渲染子组件。这在测试一个组件时,如果需要模拟子组件行为,可以更加高效。 find:用于在包装器中查找匹配选择器的元素或组件。可以用于断言组件是否正确渲染了特定的元素或组件。 setProps:用于设置组件的props。可以用于模拟不同的props值,并断言组件在不同props下的行为。 setData:用于设置组件的data。可以用于模拟不同的组件状态,并断言组件在不同状态下的行为。 trigger:用于触发组件的事件。可以用于模拟用户交互,并断言组件在不同交互下的行为。 nextTick:用于等待Vue的异步更新完成。可以在断言之前等待组件的异步更新完成,以确保断言的准确性。 expect:用于断言组件的行为和状态。可以使用expect来断言组件是否正确渲染、是否触发了特定的事件、是否更新了特定的数据等。
介绍一下Vue 2和Vue 3的主要区别和改进之处。 Vue 3的Composition API是什么?它与Vue 2的Options API有什么不同? 什么是响应式数据,在Vue中如何实现响应式数据? Vue 2中的v-bind和v-model指令有什么作用?Vue 3中是否有类似的指令? Vue 2和Vue 3中的虚拟DOM是如何工作的?有哪些优化措施? 什么是Vue Router?请解释一下Vue 2和Vue 3中的路由配置和导航守卫的不同之处。 在Vue 2和Vue 3中如何使用Vuex进行状态管理?是否有任何改进或新特性? Vue 3中的推导式props(Props Composition)是什么?它与Vue 2中的props有什么不同? Vue 2和Vue 3中的异步组件(Async Components)是如何工作的?有什么优点? 在Vue 3中,什么是Teleport(瞬移)?有什么用途和优势? 如何在Vue 2和Vue 3中实现服务端渲染(SSR)? Vue 3的性能改进有哪些方面?你在项目中如何优化Vue的性能? Vue 2和Vue 3中的动态组件(Dynamic Components)如何使用?有什么不同之处? 请解释Vue 2和Vue 3中的key属性的作用和用法。 什么是Vue Test Utils?你在写Vue组件单元测试时会用到哪些工具和方法?