侧边栏壁纸
  • 累计撰写 33 篇文章
  • 累计创建 6 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

前端常见面试题

Administrator
2025-02-26 / 0 评论 / 0 点赞 / 83 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
本文最后更新于2025-02-26,若内容或图片失效,请留言反馈。 部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1. 什么是 Vue 的钩子函数?

Vue 的钩子函数是在 Vue 实例生命周期的不同阶段自动执行的函数,能让开发者在特定时刻执行自定义逻辑。例如created钩子在实例创建完成后被调用,此时可以进行数据初始化、发起异步请求等操作;mounted钩子在组件挂载到 DOM 后调用,可用于操作 DOM 元素;updated钩子在数据更新且 DOM 重新渲染后调用,能对更新后的 DOM 进行处理;beforeDestroy钩子在实例销毁前调用,可用于清理定时器、解绑事件等收尾工作。

2. 你用过事件扩展符 (...),在什么场景下用的?

事件扩展符(...)通常指的是 ES6 中的展开运算符,在事件相关场景中,常用于将一个数组或对象展开为独立的参数。比如在 React 中,当向子组件传递多个事件处理函数时,可以通过展开运算符将事件对象展开,避免逐个传递。例如:

import React, { useState } from'react';

const ParentComponent = () => {
    const [count, setCount] = useState(0);
    const handleClick = () => {
        setCount(count + 1);
    };
    const handleMouseEnter = () => {
        console.log('Mouse entered');
    };
    const eventHandlers = {
        onClick: handleClick,
        onMouseEnter: handleMouseEnter
    };
    return (
        <div>
            <ChildComponent {...eventHandlers} />
        </div>
    );
};

const ChildComponent = ({ onClick, onMouseEnter }) => {
    return (
        <button onClick={onClick} onMouseEnter={onMouseEnter}>
            Click me
        </button>
    );
};

export default ParentComponent;

3. 什么是服务端渲染?

服务端渲染(SSR)是指在服务器端生成 HTML 页面,再将其发送到客户端的过程。与传统的客户端渲染不同,SSR 在服务器端完成页面的构建,将完整的 HTML 发送给客户端,客户端只需解析和显示页面。优势在于首屏加载速度快,因为无需等待客户端下载和执行 JavaScript 代码来生成页面,有利于 SEO,搜索引擎爬虫可以直接抓取服务器返回的 HTML 内容;缺点是服务器负载增加,开发和维护成本较高,需要同时关注服务器端和客户端的代码逻辑。

4. 前端性能优化的指标有哪些,如何量化?

  • 指标

  • 页面加载时间:从用户输入 URL 到页面完全加载完成的时间。

  • 首次内容绘制时间(FCP):浏览器首次将任何来自 DOM 的内容渲染到屏幕的时间。

  • 最大内容绘制时间(LCP):视口内最大的内容元素加载完成的时间。

  • 可交互时间(TTI):页面达到完全可交互状态所需的时间。

  • 量化工具

  • Chrome DevTools:Performance 面板可以记录和分析页面加载过程,提供详细的时间线和性能指标数据。

  • Lighthouse:一款开源的自动化工具,可对网页进行性能、可访问性等方面的评估,并给出详细的报告和优化建议。

  • PageSpeed Insights:Google 提供的工具,能分析网页性能,并给出优化建议和分数。

5. 你知道哪些前端性能优化的手段?

  • 代码层面:压缩和合并 CSS、JavaScript 文件,减少文件体积和 HTTP 请求数;使用代码拆分(如 Webpack 的splitChunks),将大的代码文件拆分成多个小文件,按需加载;优化算法和数据结构,减少不必要的计算和内存占用。

  • 资源加载:使用浏览器缓存,设置合理的缓存策略,让静态资源在浏览器中缓存,减少重复加载;图片优化,压缩图片大小,使用合适的图片格式(如 WebP 格式,在支持的浏览器中有更好的压缩比),使用srcset和picture标签实现响应式图片加载。

  • 渲染优化:减少 DOM 操作,批量修改 DOM,使用requestAnimationFrame代替setTimeout来执行动画和页面更新操作,以提高动画流畅度;避免强制同步布局,例如在修改元素样式后,立即获取元素的布局信息(如offsetWidth、scrollTop等),会导致浏览器重新计算布局,影响性能。

6. React 中的 Hooks 有哪些优缺点?

  • 优点

  • 函数组件复用状态逻辑:Hooks 允许在不编写类组件的情况下使用状态和其他 React 特性,方便在不同函数组件间复用状态逻辑,例如useState、useEffect等。

  • 简化代码结构:相比类组件,Hooks 使代码更简洁,避免了复杂的this绑定问题和生命周期方法的混乱。

  • 更清晰的代码逻辑:useEffect可以将副作用操作(如数据获取、订阅事件等)集中管理,使代码逻辑更清晰。

  • 缺点

  • 学习曲线:对于习惯类组件的开发者,Hooks 的概念和用法需要一定时间学习和适应。

  • 滥用风险:如果过度使用或使用不当,可能会导致代码难以理解和维护,例如在useEffect中依赖项设置不正确可能导致不必要的重复渲染。

7. React 的事件绑定原理是什么?

React 的事件绑定并非直接绑定在 DOM 元素上,而是采用事件代理机制。React 在最外层的 DOM 元素(通常是document)上统一监听所有事件,当事件触发时,React 会根据事件类型和目标元素,在内部维护的事件映射表中找到对应的事件处理函数并执行。这种机制减少了内存消耗,提高了事件处理效率,同时也方便对事件进行统一管理和处理,例如对事件进行合成、批量处理等。

8. setState 是同步还是异步的?

setState在 React 中通常是异步的。这是为了性能优化,React 会将多个setState操作合并成一次批量更新,减少不必要的重新渲染。例如在一个循环中多次调用setState,如果是同步更新,会导致多次重新渲染,影响性能。但在某些情况下,setState也可以表现为同步,比如在setTimeout、Promise等异步回调中,或者在原生 DOM 事件处理函数中,setState是同步的。

9. ReactRouter 的基本用法是什么?

ReactRouter 是用于在 React 应用中实现路由功能的库。基本用法如下:

import React from'react';
import ReactDOM from'react-dom';
import { BrowserRouter as Router, Routes, Route } from'react-router-dom';
import HomePage from './HomePage';
import AboutPage from './AboutPage';

const App = () => {
    return (
        <Router>
            <Routes>
                <Route path="/" element={<HomePage />} />
                <Route path="/about" element={<AboutPage />} />
            </Routes>
        </Router>
    );
};

ReactDOM.render(<App />, document.getElementById('root'));

在上述代码中,Router组件包裹整个应用,提供路由功能;Routes组件用于定义路由规则;Route组件定义具体的路由路径和对应的组件,当 URL 路径匹配Route的path时,会渲染对应的element组件。

10. Vue-router 如何实现懒加载?

Vue-router 实现懒加载有两种常见方式:

  • 异步组件:使用import()语法,将组件定义为异步加载。例如:

import { createRouter, createWebHistory } from 'vue-router';

const router = createRouter({
    history: createWebHistory(),
    routes: [
        {
            path: '/home',
            name: 'Home',
            component: () => import('./views/Home.vue')
        }
    ]
});

export default router;
  • Webpack 的require.ensure:在 Webpack 环境下,也可以使用require.ensure来实现懒加载,不过import()语法更简洁和推荐。例如:

const router = new VueRouter({
    routes: [
        {
            path: '/home',
            name: 'Home',
            component: resolve => require.ensure([], () => resolve(require('./views/Home.vue')))
        }
    ]
});

11. Vue 列表为什么加 key?

在 Vue 列表中添加key主要是为了帮助 Vue 的虚拟 DOM 算法更高效地进行更新。当列表数据发生变化时,Vue 会根据key来判断哪些元素需要更新、删除或添加。如果没有key,Vue 会默认使用数组的索引作为key,但在数组元素顺序改变或有元素增删时,会导致不必要的 DOM 更新,影响性能。而使用唯一的key可以确保 Vue 准确识别每个元素,从而进行更精准的 DOM 更新,提高渲染效率。

12. 重绘和重排的区别是什么,如何避免?

  • 区别

  • 重排(回流):当 DOM 的结构、布局、尺寸等发生改变时,浏览器需要重新计算元素的几何属性,重新构建渲染树,这个过程称为重排。重排会影响到页面的布局,开销较大。

  • 重绘:当元素的外观(如颜色、背景等)发生改变,但不影响布局时,浏览器只需要重新绘制该元素,这个过程称为重绘。重绘的开销比重排小。

  • 避免方法

  • 减少 DOM 操作:批量修改 DOM,避免频繁的增删改操作。

  • 避免强制同步布局:在修改元素样式后,避免立即获取元素的布局信息(如offsetWidth、scrollTop等),因为这会导致浏览器强制同步布局,触发重排。

  • 使用requestAnimationFrame:在执行动画和页面更新操作时,使用requestAnimationFrame代替setTimeout,它会在浏览器下一次重绘之前执行,能提高动画流畅度,减少不必要的重排和重绘。

13. 如何保持前后端实时通信?

  • WebSocket:是一种基于 TCP 协议的全双工通信协议,在客户端和服务器之间建立持久连接,允许实时双向通信。例如在聊天应用中,用户发送消息后,服务器能立即接收并推送给其他用户。

  • Server-Sent Events(SSE):是一种单向的实时通信技术,服务器可以向客户端推送消息,适用于实时数据更新场景,如股票行情、新闻推送等。客户端通过EventSource对象接收服务器发送的事件流。

  • 长轮询:客户端向服务器发送请求,服务器在有新数据时才返回响应,否则保持连接等待,客户端收到响应后立即再次发送请求,实现实时通信,但相比 WebSocket 和 SSE,长轮询的开销较大。

14. fetch 请求方式有哪些?

fetch是浏览器提供的用于发起 HTTP 请求的 API,常见请求方式有:

  • POST:用于提交数据,请求参数放在请求体中,常用于表单提交、上传文件等场景,例如:

fetch('https://example.com/api/submit', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({ key: 'value' })
});
  • PUT:用于更新资源,将整个资源替换为请求体中的数据。

15. 创建 ajax 的过程是什么?

在 JavaScript 中创建 AJAX 请求的基本过程如下:

  1. 创建 XMLHttpRequest 对象:const xhr = new XMLHttpRequest();

  1. 配置请求:设置请求方法(GET、POST 等)、URL 和是否异步等,例如xhr.open('GET', 'https://example.com/api/data', true);

  1. 设置请求头(可选):如果是 POST 请求,通常需要设置Content-Type头,例如xhr.setRequestHeader('Content-Type', 'application/json');

  1. 发送请求:如果是 GET 请求,直接xhr.send();;如果是 POST 请求,将请求体数据作为参数传入,例如xhr.send(JSON.stringify({ key: 'value' }));

  1. 处理响应:通过监听xhr的onreadystatechange事件,在readyState为 4 且status为 200 时,表示请求成功,获取响应数据,例如:

xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        const response = JSON.parse(xhr.responseText);
        console.log(response);
    }
};

16. axios 的拦截器原理及应用是什么?

  • 原理:axios 的拦截器是在请求发送前或响应返回后,对请求或响应进行拦截和处理的机制。它基于 Promise 的链式调用,通过axios.interceptors.request.use和axios.interceptors.response.use方法分别添加请求拦截器和响应拦截器。请求拦截器可以在请求发送前对请求配置进行修改,如添加请求头、设置 loading 状态等;响应拦截器可以在响应返回后对响应数据进行处理,如错误统一处理、数据格式化等。

  • 应用

  • 添加请求头:在请求拦截器中添加Authorization头,用于身份验证,例如:

axios.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
});
  • 错误处理:在响应拦截器中统一处理错误,例如:

axios.interceptors.response.use(response => {
    return response;
}, error => {
    if (error.response) {
        // 处理不同的HTTP错误状态码
        switch (error.response.status) {
            case 401:
                // 处理未授权错误
                break;
            case 404:
                // 处理资源未找到错误
                break;
            default:
                break;
        }
    }
    return Promise.reject(error);
});

17. 盒模型是什么?

CSS 盒模型是用于描述 HTML 元素在页面上的布局和尺寸的概念。它由内容区(content)、内边距(padding)、边框(border)和外边距(margin)组成。盒模型分为标准盒模型和怪异盒模型(IE 盒模型)。在标准盒模型中,元素的宽度和高度仅指内容区的尺寸,计算整个元素占据空间的宽度公式为width + padding + border + margin,高度同理。在怪异盒模型中,元素的宽度和高度包含了内容区、内边距和边框,即设置的width和height属性值包含了content、padding和border,计算占据空间的宽度公式为width + margin,高度同理。可以通过box-sizing属性来切换盒模型,box-sizing: content-box表示标准盒模型(默认值),box-sizing: border-box表示怪异盒模型。

18. 伪数组和数组的区别是什么?

  • 数组:是一种有序的数据结构,具有length属性,并且可以通过数字索引访问元素,同时拥有数组的原型方法,如push、pop、map等。例如const arr = [1, 2, 3];

  • 伪数组:虽然看起来像数组,有length属性,可以通过数字索引访问元素,但不具备数组的原型方法。常见的伪数组有函数的arguments对象、document.querySelectorAll返回的结果等。例如:

function example() {
    const args = arguments;
    console.log(args.length); // 有length属性
    console.log(args[0]); // 可以通过索引访问元素
    // 但没有数组的原型方法,例如args.map is not a function
}

可以通过Array.from或展开运算符(...)将伪数组转换为真正的数组,从而使用数组的方法。

19. 如何实现可过期的 localStorage 数据?

可以通过在存储数据时,同时存储一个过期时间戳来实现。例如:

function setLocalStorageWithExpiry(key, value, ttl) {
    const now = new Date();
    const item = {
        value: value,
        expiry: now.getTime() + ttl
    };
    localStorage.setItem(key, JSON.stringify(item));
}

function getLocalStorageWithExpiry(key) {
    const itemStr = localStorage.getItem(key);
    if (!itemStr) {
        return null;
    }
    const item = JSON.parse(itemStr);
    const now = new Date();
    if (now.getTime() > item.expiry) {
        localStorage.removeItem(key);
        return null;
    }
    return item.value;
}

// 使用示例
setLocalStorageWithExpiry('userData', { name: 'John' }, 60 * 1000); // 1分钟过期
const data = getLocalStorageWithExpiry('userData');
console.log(data);

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区