欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > vue中常见面试题(会不断更新版)

vue中常见面试题(会不断更新版)

2025/3/15 15:42:08 来源:https://blog.csdn.net/qq_62541773/article/details/146258969  浏览:    关键词:vue中常见面试题(会不断更新版)

一、vue中 key 值的作用

在 Vue 中,key 是一个特殊的属性,主要用于优化虚拟 DOM 的更新过程。它的核心作用是 帮助 Vue 识别哪些节点是可复用的,哪些节点需要重新创建,从而提高渲染性能并避免不必要的 DOM 操作。

1. key 的作用

(1)标识节点的唯一性

  • key 用于标识每个节点的唯一性。

  • 当 Vue 更新虚拟 DOM 时,会通过 key 来判断新旧节点是否相同。

(2)优化列表渲染

  • 在列表渲染(如 v-for)中,key 可以帮助 Vue 更高效地更新 DOM。

  • 如果没有 key,Vue 会默认使用“就地更新”策略,可能导致错误的渲染结果或性能问题。

(3)触发组件的生命周期

  • 当 key 发生变化时,Vue 会销毁旧组件并重新创建新组件,从而触发完整的生命周期钩子(如 mountedupdated 等)。

2. key 的使用场景

(1)列表渲染(v-for

在 v-for 中,key 是必须的,用于标识每个列表项的唯一性。

<template><ul><li v-for="item in items" :key="item.id">{{ item.name }}</li></ul>
</template><script>
export default {data() {return {items: [{ id: 1, name: "Apple" },{ id: 2, name: "Banana" },{ id: 3, name: "Orange" },],};},
};
</script>

为什么需要 key

  • 如果没有 key,Vue 会默认使用索引(index)作为标识。

  • 当列表顺序发生变化时(如插入、删除、排序),Vue 可能会错误地复用节点,导致渲染问题。

(2)动态组件

在动态组件中,key 可以强制组件重新渲染。

<template><component :is="currentComponent" :key="componentKey" /><button @click="toggleComponent">Toggle Component</button>
</template><script>
export default {data() {return {currentComponent: "ComponentA",componentKey: 0,};},methods: {toggleComponent() {this.currentComponent =this.currentComponent === "ComponentA" ? "ComponentB" : "ComponentA";this.componentKey++; // 强制重新渲染},},
};
</script>

为什么需要 key

  • 当 key 发生变化时,Vue 会销毁旧组件并重新创建新组件,确保组件状态被正确重置。

3. key 的注意事项

(1)key 必须是唯一的

  • 在同一个父节点下,key 必须是唯一的。

  • 如果 key 重复,Vue 会抛出警告。

(2)不要使用索引作为 key

  • 在列表渲染中,避免使用索引(index)作为 key,因为索引无法唯一标识节点。

  • 当列表顺序发生变化时,使用索引作为 key 会导致错误的节点复用。

(3)key 的变化会触发重新渲染

  • 当 key 发生变化时,Vue 会销毁旧节点并重新创建新节点。

  • 如果需要强制重新渲染组件,可以通过修改 key 实现。

4. key 的工作原理

(1)虚拟 DOM 的 Diff 算法

  • Vue 通过虚拟 DOM 的 Diff 算法比较新旧节点。

  • key 是 Diff 算法的重要依据,用于判断节点是否相同。

(2)节点的复用

  • 如果新旧节点的 key 相同,Vue 会复用该节点,只更新其属性和子节点。

  • 如果 key 不同,Vue 会销毁旧节点并创建新节点。


二、$route和$router的区别

1. $route

(1)定义

  • $route 是一个 当前路由信息对象,包含了当前 URL 解析后的信息。

  • 它是只读的,不能直接修改。

(2)包含的属性

  • path:当前路由的路径(如 /home)。

  • params:动态路由参数(如 /user/:id 中的 id)。

  • query:URL 查询参数(如 ?name=John 中的 name)。

  • hash:URL 的哈希值(如 #section 中的 section)。

  • fullPath:完整的 URL 路径(包括路径、查询参数和哈希)。

  • name:路由的名称(如果定义了路由的 name 属性)。

  • matched:当前路由匹配的所有路由记录(数组)。

(3)使用场景

  • 获取当前路由的信息,如路径、参数、查询参数等。

  • 在组件中根据当前路由动态渲染内容。

(4)示例

// 路由配置
const routes = [{ path: "/user/:id", component: User },
];// 在组件中访问 $route
export default {mounted() {console.log(this.$route.path); // 输出当前路径,如 "/user/123"console.log(this.$route.params.id); // 输出动态参数,如 "123"},
};

2. $router

(1)定义

  • $router 是 路由实例,提供了路由的导航方法。

  • 它是可操作的,可以通过它进行路由跳转、前进、后退等操作。

(2)常用的方法

  • push:导航到一个新路由,会向历史记录中添加一条记录。

    this.$router.push("/home");
    this.$router.push({ path: "/home" });
    this.$router.push({ name: "user", params: { id: 123 } });
  • replace:导航到一个新路由,但不会向历史记录中添加记录。

    this.$router.replace("/home");
  • go:在历史记录中前进或后退。

    this.$router.go(-1); // 后退一步
    this.$router.go(1);  // 前进一步
  • back:后退到上一个路由。

    this.$router.back();
  • forward:前进到下一个路由。

    this.$router.forward();

(3)使用场景

  • 在代码中动态导航到不同的路由。

  • 控制路由的历史记录(前进、后退等)。

(4)示例

export default {methods: {navigateToHome() {this.$router.push("/home"); // 跳转到首页},navigateBack() {this.$router.go(-1); // 返回上一页},},
};

3. $route 和 $router 的区别

特性$route$router
类型当前路由信息对象路由实例
是否可修改只读可操作
主要用途获取当前路由的信息(路径、参数等)进行路由导航(跳转、前进、后退等)
常用属性/方法pathparamsqueryhashpushreplacegoback

4. 总结

  • $route:用于获取当前路由的信息,如路径、参数、查询参数等。

  • $router:用于操作路由,如跳转、前进、后退等。


三、路由的两种模式(Hash 模式和History 模式)

Vue Router 是 Vue.js 官方的路由管理器,支持两种路由模式:

  1. Hash 模式(默认模式)

  2. History 模式

这两种模式的主要区别在于 URL 的表现形式 和 实现原理

1. Hash 模式

(1)特点

  • URL 中带有 # 符号,例如:http://example.com/#/home

  • # 后面的内容不会发送到服务器,因此不需要服务器额外配置。

(2)实现原理

  • 基于浏览器的 hashchange 事件

  • 当 URL 的哈希部分(# 后面的内容)发生变化时,页面不会重新加载,但会触发路由更新。

(3)优点

  • 兼容性好,支持所有浏览器(包括 IE9 及以下)。

  • 不需要服务器额外配置。

(4)缺点

  • URL 中带有 #,不够美观。

(5)配置

const router = new VueRouter({mode: "hash", // 默认模式,可以不写routes: [{ path: "/home", component: Home },{ path: "/about", component: About },],
});

2. History 模式

(1)特点

  • URL 是干净的,没有 #,例如:http://example.com/home

  • 基于 HTML5 的 History APIpushStatereplaceState)。

(2)实现原理

  • 使用 history.pushState 和 history.replaceState 来修改浏览器的历史记录。

  • 当用户点击浏览器的前进/后退按钮时,会触发 popstate 事件,Vue Router 会根据当前 URL 更新路由。

(3)优点

  • URL 更美观,没有 #

  • 更适合需要 SEO 的场景。

(4)缺点

  • 需要服务器支持,否则刷新页面会返回 404。

  • 兼容性较差,不支持 IE9 及以下浏览器。

(5)配置

const router = new VueRouter({mode: "history", // 使用 History 模式routes: [{ path: "/home", component: Home },{ path: "/about", component: About },],
});

(6)服务器配置

由于 History 模式的 URL 是虚拟的,刷新页面时服务器会尝试查找对应的文件,导致 404 错误。因此,需要在服务器端配置一个 回退路由,将所有请求重定向到 index.html

  • Nginx 配置

    location / {try_files $uri $uri/ /index.html;
    }

3. Hash 模式 vs History 模式

特性Hash 模式History 模式
URL 表现形式带有 #,如 http://example.com/#/home无 #,如 http://example.com/home
实现原理基于 hashchange 事件基于 History API (pushStatereplaceState)
兼容性兼容所有浏览器不兼容 IE9 及以下浏览器
服务器配置不需要需要配置回退路由
SEO 支持不支持支持
美观性URL 带有 #,不够美观URL 干净,更美观

4. 总结

  • Hash 模式:简单易用,兼容性好,适合不需要 SEO 的场景。

  • History 模式:URL 更美观,支持 SEO,但需要服务器配置。

四、v-if和v-show的区别

1. v-if 的特点

  • 实现原理v-if 是 惰性渲染 的,当条件为 false 时,元素不会渲染到 DOM 中;当条件为 true 时,元素才会被创建并插入 DOM。

  • 性能开销

    • 切换时,会销毁和重新创建 DOM 元素

    • 如果元素包含子组件,子组件的生命周期钩子(如 mounteddestroyed)也会被触发。

  • 适用场景

    • 元素或组件的切换频率较低。

    • 初始条件为 false 时,避免渲染不必要的 DOM 元素。

<div v-if="isVisible">Visible Content</div>

2. v-show 的特点

  • 实现原理v-show 是通过 CSS 的 display: none 来控制元素的显示和隐藏,元素始终会渲染到 DOM 中。

  • 性能开销

    • 切换时,只是修改 CSS 的 display 属性,不会销毁和重新创建 DOM 元素。

    • 适合频繁切换的场景,性能开销较小。

  • 适用场景

    • 元素或组件的切换频率较高。

    • 初始条件为 true 时,元素已经渲染到 DOM 中。

<div v-show="isVisible">Visible Content</div>

3. 为什么频繁切换使用 v-show

  • 性能优势v-show 只是切换 CSS 的 display 属性,不会触发 DOM 的销毁和重建,性能开销更小。

  • 适合高频切换:例如,选项卡切换、模态框显示/隐藏等场景。

4. 为什么不频繁切换使用 v-if

  • 减少初始渲染开销:如果初始条件为 falsev-if 不会渲染元素,减少初始 DOM 的复杂度。

  • 避免不必要的 DOM 存在:如果元素不需要频繁切换,使用 v-if 可以避免 DOM 中一直存在不必要的元素。

5. 对比总结

特性v-ifv-show
实现原理条件为 true 时渲染 DOM始终渲染 DOM,通过 display 控制显示/隐藏
性能开销切换时销毁和重建 DOM,开销较大切换时只修改 CSS,开销较小
适用场景不频繁切换,初始条件为 false频繁切换,初始条件为 true
生命周期钩子切换时触发组件的生命周期钩子不触发组件的生命周期钩子

注意点: 

  • 当设置 display: none 时:

    • 元素会从 渲染树 中移除,因此不会显示在页面上,也不会占据布局空间。

    • 但是,元素仍然存在于 DOM 树 中,只是不会被渲染到页面上。

    • 元素的状态(如事件监听器、子元素等)仍然保留。

  • 当修改 display 属性为其他值(如 blockinline 等)时:

    • 元素会被重新添加到 渲染树 中,并显示在页面上。

    • 由于元素始终存在于 DOM 树中,因此不需要重新创建 DOM 元素。

6. DOM 树与渲染树的区别(扩展点)

  • DOM 树

    • DOM 树是浏览器根据 HTML 文档解析生成的树形结构,表示页面的结构和内容。

    • DOM 树中的每个节点都对应一个 HTML 元素。

    • DOM 树是持久的,除非显式地通过 JavaScript 删除或添加节点,否则 DOM 元素不会被销毁或重新创建。

  • 渲染树(Render Tree)

    • 渲染树是浏览器根据 DOM 树和 CSS 样式生成的树形结构,用于实际渲染页面。

    • 渲染树只包含需要显示的元素(例如,display: none 的元素不会包含在渲染树中)。

    • 渲染树是动态的,会根据 CSS 样式和 DOM 变化而更新。


五、vue.extend和vue.component

1. Vue2 中的 Vue.extend 和 Vue.component

(1)Vue.extend

  • 作用:创建一个组件构造器。

  • 使用场景

    • 动态创建组件实例(如弹窗、通知等)。

    • 手动控制组件的生命周期。

(2)Vue.component

  • 作用:注册全局组件。

  • 使用场景

    • 在多个地方复用组件。

    • 全局范围内使用组件。

(3) Vue2 中的示例

// Vue.extend 创建组件构造器
const MyComponent = Vue.extend({template: '<div>Hello, {{ name }}</div>',data() {return { name: 'Vue2' };},
});// Vue.component 注册全局组件
Vue.component('my-component', MyComponent);// 动态创建组件实例
const instance = new MyComponent().$mount();
document.body.appendChild(instance.$el);

2. Vue3 中的变化

在 Vue3 中,Vue.extend 和 Vue.component 仍然可以使用,但它们的推荐用法发生了变化。

(1) Vue.extend 的替代

  • Vue3 推荐使用 defineComponent 来定义组件。

  • defineComponent 提供了更好的 TypeScript 支持和更清晰的组件定义方式。

(2) Vue.component 的替代

  • Vue3 推荐使用 app.component 来注册全局组件。

  • app.component 是 Vue3 应用实例的方法,更加模块化。

(3)Vue3 中的示例

import { createApp, defineComponent } from 'vue';// 使用 defineComponent 定义组件
const MyComponent = defineComponent({template: '<div>Hello, {{ name }}</div>',data() {return { name: 'Vue3' };},
});// 创建应用实例并注册全局组件
const app = createApp({});
app.component('my-component', MyComponent);
app.mount('#app');

3. Vue3 中的推荐用法

(1)局部组件

  • 使用 defineComponent 定义组件,然后在父组件中通过 components 选项注册。

import { defineComponent } from 'vue';const ChildComponent = defineComponent({template: '<div>Child Component</div>',
});export default defineComponent({components: { ChildComponent },template: '<child-component />',
});

(2)全局组件

  • 使用 app.component 注册全局组件。

import { createApp } from 'vue';
import MyComponent from './MyComponent.vue';const app = createApp({});
app.component('my-component', MyComponent);
app.mount('#app');

(3)动态组件

  • 使用 h 函数(渲染函数)动态创建组件。

import { defineComponent, h } from 'vue';const DynamicComponent = defineComponent({props: ['componentName'],render() {return h(this.componentName);},
});

4. 现在还会使用 Vue.extend 和 Vue.component 吗?

  • Vue2:仍然会使用 Vue.extend 和 Vue.component,尤其是在动态创建组件或注册全局组件时。

  • Vue3:不推荐使用 Vue.extend 和 Vue.component,而是推荐使用 defineComponent 和 app.component

5. 总结

特性Vue2 中的用法Vue3 中的替代方案
组件定义Vue.extenddefineComponent
全局组件注册Vue.componentapp.component
动态组件创建Vue.extend + new Component()h 函数(渲染函数)
  • Vue2:继续使用 Vue.extend 和 Vue.component

  • Vue3:推荐使用 defineComponent 和 app.component,避免使用 Vue.extend 和 Vue.component

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词