前端面试题详解整理94|跨域 cors/代理 hooks usememo usecallback,react class组件有哪些可以处理组件渲染错误的

100 阅读12分钟

字节前端实习一面面经

1h
1.自我介绍
2.promise (async/await)链式调用 then catch

3.react class组件有哪些可以处理组件渲染错误的

在 React 中,Class 组件可以通过以下方法来处理组件渲染错误:

  1. componentDidCatch() 方法componentDidCatch() 是 Class 组件中的生命周期方法,用于捕获并处理组件树中任何位置的 JavaScript 错误。当组件的子组件抛出错误时,该方法会被调用,允许组件渲染一个备用 UI,而不是崩溃。它接收两个参数:error 表示捕获到的错误,info 表示错误的信息。

    class ErrorBoundary extends React.Component {
        constructor(props) {
            super(props);
            this.state = { hasError: false };
        }
    
        componentDidCatch(error, info) {
            this.setState({ hasError: true });
            // 在这里可以记录错误信息到日志
        }
    
        render() {
            if (this.state.hasError) {
                // 渲染备用 UI
                return <h1>Something went wrong.</h1>;
            }
            return this.props.children;
        }
    }
    

    使用示例:

    <ErrorBoundary>
        <MyComponent />
    </ErrorBoundary>
    
  2. 静态方法 getDerivedStateFromError()getDerivedStateFromError() 是 Class 组件中的静态方法,用于捕获并处理组件树中任何位置的 JavaScript 错误。当子组件抛出错误时,该方法会被调用,并返回一个对象,用于更新组件的状态。它在渲染阶段调用,因此它不允许在其中执行副作用。

    class ErrorBoundary extends React.Component {
        constructor(props) {
            super(props);
            this.state = { hasError: false };
        }
    
        static getDerivedStateFromError(error) {
            return { hasError: true };
        }
    
        render() {
            if (this.state.hasError) {
                // 渲染备用 UI
                return <h1>Something went wrong.</h1>;
            }
            return this.props.children;
        }
    }
    

    使用示例与上述相同。

这些方法可以用于在 Class 组件中捕获和处理组件渲染过程中的错误,并提供备用 UI 或记录错误信息的机制,以提高应用程序的可靠性和用户体验。

api /hooks usememo usecallback 类和函数组件两者的区别

useMemouseCallback 是 React Hooks 提供的两个钩子函数,用于优化函数组件的性能。它们的作用类似,都是用来避免不必要的计算和渲染。下面是它们的区别以及类组件与函数组件在使用上的差异:

  1. useMemo

    • useMemo 用于在渲染过程中对计算结果进行缓存,只有当依赖项发生变化时才重新计算。它接收一个工厂函数和一个依赖数组,并返回计算结果。
    • 在每次渲染时,useMemo 都会执行工厂函数并返回结果。只有当依赖项发生变化时,才会重新执行工厂函数。这样可以避免不必要的重复计算,提高性能。
  2. useCallback

    • useCallback 用于在渲染过程中缓存回调函数,只有当依赖项发生变化时才重新创建回调函数。它接收一个回调函数和一个依赖数组,并返回一个记忆化的回调函数。
    • 在每次渲染时,useCallback 都会返回相同的记忆化的回调函数,除非依赖项发生变化。这样可以避免不必要的回调函数创建,提高性能。
  3. 类组件与函数组件的区别

    • 在类组件中,可以使用 shouldComponentUpdatePureComponent 来进行性能优化,但需要手动编写逻辑判断是否更新组件。
    • 在函数组件中,可以使用 useMemouseCallback 来优化性能,React 会自动处理依赖项的变化并进行相应的更新。

总的来说,useMemouseCallback 都是用于性能优化的,它们的主要区别在于用途:useMemo 用于缓存计算结果,useCallback 用于缓存回调函数。在函数组件中,它们是替代类组件中 shouldComponentUpdatePureComponent 的方式来进行性能优化的工具。

4.浏览器缓存

5.跨域 cors/代理

跨域请求是指在浏览器中,当一个源(origin)的网页请求另一个源的资源时,就会发生跨域请求。跨域请求通常会受到同源策略的限制,为了解决跨域请求的问题,可以使用 CORS(跨源资源共享)或代理服务器两种方式。

1. CORS(跨源资源共享):

CORS 是一种机制,允许服务器端在响应中添加特定的 HTTP 头部,告诉浏览器是否允许跨源请求。通过在服务器端设置 CORS 头部,可以允许指定的源进行跨域访问。例如,在 Express 中可以使用 cors 中间件来设置 CORS 头部:

const express = require('express');
const cors = require('cors');

const app = express();

// 允许所有来源访问
app.use(cors());

// 或者只允许指定来源访问
// app.use(cors({
//     origin: 'http://example.com'
// }));

// 处理其他请求...

在客户端发起跨域请求时,浏览器会发送一个预检请求(OPTIONS 请求),服务器返回的响应中包含了 CORS 头部,浏览器根据这些头部判断是否允许跨域请求。

2. 代理服务器:

代理服务器是指在客户端和目标服务器之间增加一个中间层,客户端发送的请求先发送到代理服务器,再由代理服务器转发到目标服务器,目标服务器返回的响应也先发送到代理服务器,再由代理服务器返回给客户端。通过代理服务器转发请求,可以绕过浏览器的同源策略限制,实现跨域请求。

例如,可以在项目的配置中添加代理规则,将特定的请求代理到目标服务器:

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://api.example.com',
        changeOrigin: true,
        pathRewrite: { '^/api': '' }
      }
    }
  }
};

上述配置将以 /api 开头的请求代理到 http://api.example.com,并将请求路径重写为空,这样在客户端发起 /api 开头的请求时,实际上会被代理到 http://api.example.com

选择使用 CORS 还是代理服务器取决于具体的情况和需求,通常情况下推荐使用 CORS,因为它更简单直接,并且不需要额外的服务器配置。而代理服务器更适用于一些复杂的场景,如需要在客户端请求之前对请求进行处理或者需要转发多个源的请求到不同的目标服务器等情况。 6.同源策略

7.cookie/token

Cookie 和 Token 是常用的身份验证机制,用于在客户端和服务器之间传递身份信息。它们有一些共同点,但也有一些不同之处。

Cookie:

  1. 存储位置:Cookie 是存储在客户端的一小段文本信息,通过浏览器的 Cookie 机制存储在用户的计算机上,每次发送 HTTP 请求时都会被自动携带到服务器端。

  2. 大小限制:每个 Cookie 的大小通常受到浏览器限制,一般为几 KB 到几 MB 不等。

  3. 安全性:Cookie 存储在客户端,因此可以被用户修改、删除或者被窃取,存在安全隐患。为了提高安全性,可以使用一些安全标志,如 HttpOnly、Secure 和 SameSite。

  4. 跨域限制:Cookie 存在同源策略限制,不能在不同域名之间共享。

Token:

  1. 存储位置:Token 是一种基于 JSON 格式的身份认证令牌,通常存储在客户端的本地存储(LocalStorage 或 SessionStorage)中。每次发送 HTTP 请求时,需要手动将 Token 添加到请求头中。

  2. 大小限制:Token 的大小通常没有明确的限制,但应该尽量保持较小的大小,以减少网络传输的负担。

  3. 安全性:Token 存储在客户端,但相比于 Cookie,它更加安全,因为可以通过一些加密算法(如 HMAC、JWT 等)来保护 Token 的内容,从而防止被篡改或窃取。

  4. 跨域限制:Token 可以在不同域名之间共享,因此更适合于跨域认证和授权。

选择使用 Cookie 还是 Token 取决于具体的场景需求和安全考虑:

  • 如果需要在同一域名下进行用户身份验证,且不需要在不同域名之间共享身份信息,可以考虑使用 Cookie。
  • 如果需要在不同域名之间共享用户身份信息,或者需要更高的安全性保护,可以考虑使用 Token。

在实际应用中,通常会根据具体的需求和安全考虑,选择合适的身份认证机制,并结合其他安全措施来保护用户的身份信息。

8.axios/ajax

Axios 和 AJAX 都是用于发起 HTTP 请求的工具,它们有一些相似之处,但也有一些重要的区别。

AJAX(Asynchronous JavaScript And XML):

  1. 原生 API:AJAX 是一种基于原生 JavaScript 的技术,使用 XMLHttpRequest 对象来实现异步通信,可以在不刷新整个页面的情况下与服务器进行数据交换。

  2. 底层细节:AJAX 是一种底层的技术,需要手动处理请求的创建、发送、响应的处理等细节,代码相对复杂。

  3. 支持性:由于 AJAX 是基于原生 JavaScript 的技术,因此在各种现代浏览器中都有良好的支持。

Axios:

  1. 基于 Promise:Axios 是一个基于 Promise 的 HTTP 客户端,可以用于浏览器和 Node.js 环境中,支持异步请求和响应处理。

  2. 简洁易用:Axios 提供了简洁的 API 接口,易于使用,支持请求和响应拦截、请求取消、全局配置等功能,提供了更好的开发体验。

  3. 功能强大:Axios 支持多种请求方法,如 GET、POST、PUT、DELETE 等,支持 Promise API,支持请求和响应的拦截器、转换器等功能。

  4. 错误处理:Axios 提供了丰富的错误处理机制,可以轻松地捕获并处理请求和响应过程中的错误,如网络错误、超时错误等。

选择使用 Axios 还是 AJAX 取决于具体的需求和项目情况:

  • 如果只需要在现代浏览器中进行简单的 AJAX 请求,并且对代码的大小和性能要求不高,可以考虑使用原生的 AJAX 技术。
  • 如果需要在多个环境中(包括浏览器和 Node.js)使用统一的 API 来处理 HTTP 请求,并且需要更丰富的功能和更好的开发体验,推荐使用 Axios。

总的来说,Axios 是一个功能强大、易用且具有良好支持的 HTTP 客户端,适用于大多数的 HTTP 请求场景,并且提供了更好的开发体验和更丰富的功能。

9.cssmodule原理

CSS 模块(CSS Modules)是一种用于解决 CSS 样式全局污染和作用域隔离问题的技术。它通过将 CSS 文件转换成局部作用域的模块,使得每个模块中的 CSS 样式只对当前模块有效,从而避免了全局污染和样式冲突的问题。

CSS 模块的原理主要包括以下几个步骤:

  1. 局部作用域: CSS 模块将每个 CSS 文件视为一个独立的模块,样式仅在当前模块内部生效。这意味着每个模块中的类名、ID、选择器都是局部作用域的,不会影响其他模块。

  2. 唯一标识符: CSS 模块会为每个类名和选择器生成一个唯一的标识符,通常是使用哈希算法根据类名和文件路径生成的。这样可以确保不同模块中的类名不会冲突。

  3. 导出和导入: CSS 模块允许在 JavaScript 文件中使用 import 导入样式表,并将样式表作为一个对象导出。导入的样式表对象中包含了经过处理的类名和选择器,可以在 JavaScript 文件中直接使用。

  4. 运行时替换: 在构建过程中,CSS 模块会将样式表中的类名和选择器替换为对应的唯一标识符。当 JavaScript 文件中使用导入的样式表对象时,运行时会根据实际情况动态替换类名和选择器。

通过以上步骤,CSS 模块实现了样式的局部作用域和作用域隔离,避免了全局样式的污染和样式冲突。同时,它还提供了更好的模块化和可重用性,使得样式表可以像 JavaScript 模块一样进行导入和导出,方便了样式的组织和管理。

10.堆栈

11.express 跨域中间件

在 Express 中实现跨域请求可以使用 cors 中间件。cors 中间件是一个 Node.js 包,用于处理跨域请求。

首先,确保你已经安装了 cors 包:

npm install cors

然后,在 Express 应用中使用 cors 中间件:

const express = require('express');
const cors = require('cors');

const app = express();

// 使用 cors 中间件处理跨域请求
app.use(cors());

// 定义路由
app.get('/api/data', (req, res) => {
    // 处理 GET 请求并返回数据
    res.json({ message: 'Hello from the server!' });
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

在上面的示例中,我们首先导入了 Express 和 cors 模块。然后,使用 app.use(cors())cors 中间件添加到 Express 应用中,以处理所有的跨域请求。

使用 cors() 可以设置一些选项来配置跨域请求的行为,例如允许特定的域名或方法。以下是一个配置示例:

// 允许特定域名访问
app.use(cors({
    origin: 'http://example.com'
}));

// 允许所有域名访问
app.use(cors({
    origin: '*'
}));

// 允许指定的多个域名访问
app.use(cors({
    origin: ['http://example1.com', 'http://example2.com']
}));

这样就可以在 Express 应用中使用 cors 中间件来处理跨域请求了。

12.手写 头部底部固定中间两栏布局

下面是一个简单的示例,展示了如何手写一个具有头部、底部和固定中间两栏布局的 HTML 和 CSS:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fixed Header Footer with Centered Columns Layout</title>
<style>
    body {
        margin: 0;
        font-family: Arial, sans-serif;
    }

    .container {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
    }

    header, footer {
        background-color: #333;
        color: #fff;
        padding: 10px;
        text-align: center;
    }

    .main-content {
        flex-grow: 1;
        display: flex;
        justify-content: center;
        align-items: center;
        background-color: #f0f0f0;
    }

    .sidebar {
        width: 200px;
        background-color: #ccc;
        padding: 20px;
    }
</style>
</head>
<body>
    <div class="container">
        <header>
            <h1>Fixed Header</h1>
        </header>
        <div class="main-content">
            <div class="sidebar">
                <h2>Sidebar</h2>
                <p>This is a fixed sidebar content.</p>
            </div>
            <div class="content">
                <h2>Main Content</h2>
                <p>This is the main content area.</p>
            </div>
        </div>
        <footer>
            <p>Fixed Footer</p>
        </footer>
    </div>
</body>
</html>

这个布局由三个部分组成:头部(header)、中间主要内容区域(main-content),和底部(footer)。其中,主要内容区域又分为固定宽度的侧边栏(sidebar)和居中显示的主要内容(content)两部分。

CSS 中使用了 flex 布局来实现上述布局。.container 设置为 display: flex; flex-direction: column;,使得整个页面呈现竖直方向的布局,头部、主要内容区域、底部依次排列。.main-content 设置为 display: flex; justify-content: center; align-items: center;,使得其中的内容水平和垂直居中显示。.sidebar 设置了固定宽度,.content 没有设置宽度,因此会占据剩余的空间,实现了主要内容区域的居中显示。

反问
面试官真的好好 会给很真诚的学习建议

作者:offer来offer从四面八方来来
链接:www.nowcoder.com/feed/main/d…
来源:牛客网