前端高频面试题day2

如何在vue3中使用defineAsyncComponent实现异步组件加载

在 Vue 3 中,使用 defineAsyncComponent 实现异步组件加载的步骤如下:

  1. 引入方法 :从 Vue 中导入 defineAsyncComponent
  2. 定义异步组件 :通过 defineAsyncComponent 包装一个返回 Promise 的工厂函数,Promise 解析后返回组件。
  3. 使用组件:在模板中正常使用该异步组件。

代码示例

javascript 复制代码
import { defineAsyncComponent } from 'vue';

const AsyncComp = defineAsyncComponent(() => 
  import('./MyComponent.vue')
);

export default {
  components: { AsyncComp }
};

特点

  • 支持懒加载,优化性能。
  • 可选配置如 loadingComponenterrorComponent 提升用户体验。

v-show和v-if有什么区别?使用场景分别是什么

区别:

  1. 实现方式v-show通过display: none控制显示,元素始终在DOM中;v-if条件为假时直接移除元素,为真时重新渲染。
  2. 性能v-show适合频繁切换 (仅改CSS);v-if适合不常变化的条件(初始渲染更轻量)。
  3. 特性v-if支持v-else/v-else-if,切换会触发组件销毁/创建钩子;v-show不支持且不会。

场景:

  • v-show:需频繁切换显示的元素(如快速切换的标签页)。
  • v-if:条件极少变化、复杂组件或初始无需渲染的场景。

vue计算属性的函数名和data中的属性可以同名吗?为什么?

在 Vue 中,计算属性的函数名和 data 中的属性 不可以同名,原因如下:


原因:

  1. 属性覆盖机制

    Vue 将 datacomputed 等属性都挂载到 Vue 实例上。当名称冲突时,后定义的属性会覆盖先定义的属性

    • 初始化顺序为:props → methods → data → computed → watch
    • 因此,若计算属性与 data 同名,计算属性会覆盖 data 中的同名属性 ,导致 data 中的原始数据无法被访问。
  2. 不可预测的逻辑错误

    • 在模板中使用该名称时,实际调用的是计算属性的结果 ,而非 data 中的原始数据。
    • 若尝试修改 data 中的同名属性,会因计算属性的只读性导致错误(除非计算属性有 setter)。

Vue 的警告机制

  • 当发生命名冲突时,Vue 会通过控制台输出警告,例如:
    [Vue warn]: The computed property "xxx" is already defined in data.

最佳实践

  1. 命名规范

    • data 属性与计算属性使用不同名称

      javascript 复制代码
      data() {
        return {
          originalMessage: 'Hello' // 原始数据
        };
      },
      computed: {
        uppercaseMessage() { // 计算属性名与 data 区分
          return this.originalMessage.toUpperCase();
        }
      }
  2. 代码审查

    • 通过 ESLint 或 TypeScript 类型检查避免同名冲突(如定义接口时明确区分字段)。

总结

  • 技术上允许同名,但会导致属性覆盖和逻辑混乱。
  • 强烈建议避免同名,通过清晰的命名规范提升代码可维护性。

如何监听Vuex数据的变化?

在 Vue 中监听 Vuex 数据的变化,可以通过以下几种方法实现,根据场景选择最合适的方案:


1. 计算属性 + watch

  • 适用场景:在组件内监听特定状态的变化。
  • 步骤
    1. 通过计算属性映射 Vuex 状态。
    2. watch 中监听计算属性的变化。

2. 直接使用 watch 监听 Vuex 状态

  • 适用场景:直接监听 Vuex 状态,无需计算属性。
  • 步骤
    1. watch 中直接指定 Vuex 状态的路径。
    2. 可选 deep 选项处理嵌套对象/数组。

3. Vuex 的 store.watch 方法

  • 适用场景:在非组件环境(如工具函数、服务层)监听状态变化。
  • 步骤
    1. 通过 store.watch 传入状态获取函数和回调。
    2. 返回的取消函数用于停止监听。

性能注意事项

  • 嵌套对象/数组 :使用 deep: true 时性能开销较大,尽量避免深层监听。
  • 取消监听 :在组件销毁前调用 unwatch()unsubscribe(),防止内存泄漏。
  • 优先级 :频繁变化的状态建议用计算属性,减少 watch 的回调执行次数。

Vue Router路由守卫

  1. 什么是路由守卫?

    路由守卫是 Vue Router 提供的钩子函数,用于在路由跳转的不同阶段插入控制逻辑(如权限验证、数据预加载、页面标题切换等)。它允许开发者在导航过程中拦截、检查或修改路由行为。

  2. 路由守卫的分类

    Vue Router 的路由守卫分为三类:

    • 全局守卫 :对所有路由生效,如 beforeEachbeforeResolveafterEach
    • 路由独享守卫 :仅对特定路由生效,定义在路由配置的 beforeEnter 属性中。
    • 组件内守卫 :定义在组件内部,如 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

如何解决前端接口大规模并发问题

一、前端优化方案

  1. 减少请求次数

    • 合并请求(Batch API)
      • 场景:多个小请求合并为一个请求(如实时搜索、分页加载)。

      • 实现:使用防抖/节流或自定义批量接口。

      • 代码示例(防抖合并请求)

        javascript 复制代码
        let timer = null;
        const requests = [];
        function debounceRequest() {
          if (timer) clearTimeout(timer);
          timer = setTimeout(() => {
            // 合并请求并发送
            const batchRequest = requests.map(req => req.params);
            fetch('/batch-endpoint', { method: 'POST', body: JSON.stringify(batchRequest) })
              .then(data => handleResponse(data));
            requests.length = 0; // 清空队列
          }, 300);
        }
        // 每次触发请求时加入队列
        function addRequest(params) {
          requests.push({ params });
          debounceRequest();
        }
      • 接口聚合(BFF层)

        • 原理:通过后端为前端(BFF)聚合多个接口,减少前端请求次数。
        • 示例 :将多个独立接口合并为一个聚合接口 /api/v1/combined
      • 数据缓存

        • 浏览器缓存 :通过 Cache-ControlETag 减少重复请求。

          • 协商缓存(动态数据):ETag: "abc123"
        • 本地存储 :使用 localStorageIndexedDB 缓存低频数据。

          javascript 复制代码
          const CACHE_KEY = 'user-profile';
          const cachedData = localStorage.getItem(CACHE_KEY);
          if (cachedData) {
            return JSON.parse(cachedData);
          } else {
            return fetch('/api/user')
              .then(data => {
                localStorage.setItem(CACHE_KEY, JSON.stringify(data));
                return data;
              });
          }
      • 请求去重

        • 实现 :使用 Map 存储进行中的请求,避免重复发送。

          javascript 复制代码
          const requestMap = new Map();
          async function sendRequest(url, params) {
            const key = `${url}-${JSON.stringify(params)}`;
            if (requestMap.has(key)) {
              return requestMap.get(key);
            }
            const promise = fetch(url, { method: 'POST', body: params })
              .then(response => response.json())
              .finally(() => requestMap.delete(key));
            requestMap.set(key, promise);
            return promise;
          }
    1. 控制并发请求

      • 请求队列(限流)

        • 原理:通过队列控制同时发起的请求数量,避免浏览器资源耗尽。

        • 代码示例(自定义请求队列)

          javascript 复制代码
          class RequestQueue {
            constructor(maxConcurrency = 5) {
              this.maxConcurrency = maxConcurrency;
              this.current = 0;
              this.queue = [];
            }
            add(promise) {
              return new Promise((resolve, reject) => {
                this.queue.push({ promise, resolve, reject });
                this.process();
              });
            }
            async process() {
              if (this.current >= this.maxConcurrency || this.queue.length === 0) return;
              const task = this.queue.shift();
              this.current++;
              try {
                const result = await task.promise;
                task.resolve(result);
                this.current--;
                this.process();
              } catch (error) {
                task.reject(error);
                this.current--;
                this.process();
              }
            }
          }
          // 使用示例
          const queue = new RequestQueue(3);
          const requests = [fetch('/api/1'), fetch('/api/2'), ...];
          requests.forEach(req => queue.add(req));
      • 懒加载与分页

        • 场景:对非首屏数据延迟加载(如表格分页、图片懒加载)。
    2. 优化请求效率

      • 静态资源优化
        • CDN加速:将静态资源托管到 CDN,减少服务器压力。
        • 资源合并 :合并 CSS/JS 文件,减少请求数(如通过 Webpack 的 optimization.splitChunks)。
        • 图片优化:使用 WebP 格式、懒加载、按需加载不同分辨率图片。
      • 使用 HTTP/2
        • 优势:支持多路复用,减少请求开销。

# typeof和instanceof有什么区别

typeof 的场景

检测基本类型(如 numberstringboolean)、函数或 undefined

instanceof 的场景

检测对象是否为某个构造函数的实例(如数组、自定义对象、Date 对象等)。

避免陷阱

  • typeof null 返回 "object"(需额外判断 === null)。
  • 数组用 Array.isArray() 替代 instanceof Array 更可靠。
  • 跨窗口环境(如 iframe)中 instanceof 可能失效。

js中null和undefined的区别

nullundefined 的区别

  • null :表示空值 ,需手动赋值(如 let user = null),类型为 Null
  • undefined :表示变量未声明/未赋值 或属性不存在,类型为 Undefined

关键差异

  1. 类型检测
    • typeof null 返回 "object"(历史遗留问题),typeof undefined 返回 "undefined"
  2. 比较结果
    • null == undefinedtrue,但 null === undefinedfalse
  3. 用途
    • null 是主动设置的"无值",undefined 是系统默认的"未定义"。

如何判断js变量是数组

判断变量是否为数组的最简方法:

  1. Array.isArray()

    javascript 复制代码
    Array.isArray([1,2,3]); // true
    Array.isArray({});      // false
  2. Object.prototype.toString

    javascript 复制代码
    Object.prototype.toString.call(arr) === "[object Array]";
  3. instanceof(需谨慎)

    javascript 复制代码
    arr instanceof Array; // 可能受跨窗口影响

关键点:

  • 推荐 :优先用 Array.isArray()(简洁可靠)或 toString(跨环境通用)。
  • 慎用instanceofconstructor 可能因环境问题出错。
  • 禁用typeof 返回 object,无法准确判断数组。

Js有哪些数据类型,它们的区别是什么

JavaScript 数据类型及区别


原始类型(7种)

直接存值,不可变,存栈内存 ,用 typeof 检测:

  • undefined :未定义(let a;)。
  • null :空值(类型检测异常:typeof null → "object")。
  • boolean :布尔值(true/false)。
  • number :数值(含整数/浮点/NaN/Infinity)。
  • string :字符串(不可变,如 "abc")。
  • symbol:唯一标识符(ES6,防属性冲突)。
  • bigint :大整数(ES10,后缀 n,如 123n)。

引用类型(对象)

堆内存 ,通过引用访问,可变,用 instanceofObject.prototype.toString 检测:

  • Object :键值对容器({key: value})。
  • Array :有序集合([1, "a", true])。
  • Function :可执行函数(function() {})。
  • DateRegExp 等:内置对象(如日期、正则)。
  • ES6 新增MapSetPromise 等。

核心区别

特征 原始类型 引用类型
存储位置 栈内存(直接存值) 堆内存(存引用地址)
值传递方式 按值拷贝(独立) 按引用拷贝(指向同一内存)
可变性 不可变 可变(如数组、对象可修改)
类型检测 typeofnull 异常) instanceof / Object.prototype.toString

关键注意

  • typeof null → "object" 是 JavaScript 的历史遗留问题。
  • 判断数组用 Array.isArray(),而非 typeof
复制代码
相关推荐
贾公子5 分钟前
form组件的封装(element ui ) 简单版本
前端·javascript
贾公子6 分钟前
下拉框组件的封装(element ui )
前端·javascript
贾公子7 分钟前
ElementUI,在事件中传递自定义参数的两种方式
前端·javascript
贾公子8 分钟前
基于Vue3 + Typescript 封装 Element-Plus 组件
前端·javascript
vim怎么退出9 分钟前
43.验证二叉搜索树
前端·leetcode
记得开心一点嘛9 分钟前
使用Three.js搭建自己的3Dweb模型(从0到1无废话版本)
前端·javascript·three.js
这颗橘子不太甜QAQ9 分钟前
patch-package使用详解
前端·npm
贾公子9 分钟前
JavaScript 中的类型相等性比较 (宽松比较的小问题)
前端·javascript
我爱学习_zwj11 分钟前
Webpack模块打包工具
前端
贾公子12 分钟前
JavaScript 中那些不常见的 for 循环命名与高阶用法
前端·javascript