前端面试题详解整理68|Vue 3 响应式原理,渲染,diff算法,vue router实现,http协议,xss,csrf,typescript优势,手撕pr

85 阅读10分钟

腾讯实习基地-前端(一面挂)

不知道怎么搞的,后来面试的是全栈的岗位
1.vue3响应式原理
2.vue3 渲染
3. diff算法

1. Vue 3 响应式原理

Vue 3 中的响应式原理和 Vue 2 相比有所改变,主要基于 ES6 中的 Proxy 对象来实现。具体实现步骤如下:

  1. 初始化阶段:在组件初始化时,Vue 3 会递归地遍历组件的所有属性,并使用 Proxy 对象对其进行代理。

  2. 依赖收集:当访问被代理的属性时,Vue 3 会将当前组件的依赖关系收集起来,并建立响应式依赖关系图。

  3. 触发更新:当响应式数据发生变化时,Proxy 对象会捕获到变化,触发相应的更新函数。

  4. 更新视图:根据依赖关系图,Vue 3 知道哪些组件依赖于发生变化的数据,从而只更新受影响的组件,提高了性能。

2. Vue 3 渲染

Vue 3 的渲染过程分为以下几个步骤:

  1. 解析模板:Vue 3 会解析组件的模板,并将其转换成渲染函数。

  2. 生成虚拟 DOM:根据渲染函数生成虚拟 DOM(Virtual DOM),表示组件的结构和内容。

  3. 进行 diff 比对:Vue 3 使用 diff 算法比对新旧虚拟 DOM,找出需要更新的部分。

  4. 执行更新:根据 diff 比对结果,更新实际 DOM,将变化应用到页面上。

  5. 触发生命周期钩子:在更新完成后,触发相应的生命周期钩子函数,如 beforeUpdateupdated 等。

3. Diff 算法

Diff 算法是用于比较两棵树的差异并将变化应用到真实 DOM 上的算法。Vue 3 中采用了优化过的虚拟 DOM Diff 算法,具体步骤如下:

  1. 树的遍历:从根节点开始,逐层遍历两棵树的节点。

  2. 节点比较:对比同级节点,找出需要更新的节点。

  3. 子节点比较:如果某个节点需要更新,则递归比较其子节点,找出子节点中需要更新的部分。

  4. 生成变更列表:根据比较结果生成变更列表,记录需要添加、删除、更新的节点。

  5. 应用变更:根据变更列表,将变更应用到真实 DOM 上,更新页面。

Diff 算法通过高效地比较虚拟 DOM 的差异,可以最小化更新的开销,提高页面渲染的性能。

5. vue router实现
6. http协议
7. xss、csrf攻击预防

5. Vue Router 实现

Vue Router 是 Vue.js 的官方路由管理器,用于实现 SPA(单页面应用)的路由功能。Vue Router 的实现主要包括以下几个方面:

  1. 路由配置:通过定义路由配置表,将路径映射到对应的组件。可以配置路由参数、嵌套路由、命名路由等。

  2. 路由导航:Vue Router 提供了 router-link 组件用于在应用中进行导航,并且可以通过编程式导航实现跳转,如 $router.push()$router.replace() 等。

  3. 路由视图:在根组件中定义 <router-view> 组件,用于渲染匹配到的路由组件。

  4. 路由守卫:Vue Router 提供了全局的导航守卫、路由独享的守卫以及组件内的守卫,用于控制导航行为,实现登录验证、页面权限控制等功能。

  5. 路由模式:Vue Router 支持多种路由模式,包括 hash 模式、history 模式和 abstract 模式,可以根据项目需求选择合适的模式。

Vue Router 的实现基于 Vue.js 的生态系统,与 Vue 组件和数据绑定深度集成,提供了强大的路由功能,可以实现灵活而高效的单页面应用开发。

6. HTTP 协议

HTTP(Hypertext Transfer Protocol)是一种用于传输超文本数据的应用层协议,基于客户端-服务器架构,使用 TCP 连接进行通信。HTTP 协议主要包括以下几个方面:

  1. 请求-响应模型:HTTP 使用请求-响应模型,客户端发送请求到服务器,服务器处理请求并返回响应。

  2. 无状态性:HTTP 是无状态协议,即服务器不会保留之前的请求信息,每个请求都是独立的,需要在请求和响应中添加额外的信息来实现状态管理。

  3. 报文格式:HTTP 报文由请求报文和响应报文组成,包括请求行、请求头、请求体(对于 POST 请求)、状态行、响应头和响应体等部分。

  4. 连接管理:HTTP/1.1 引入了持久连接,使得多个请求可以复用同一个 TCP 连接,提高了性能。

  5. 安全性:HTTP 不具备安全性,通信内容都是明文传输的,容易被窃听和篡改。为了提高安全性,可以使用 HTTPS 协议进行加密通信。

7. XSS、CSRF 攻击预防

  • XSS(跨站脚本攻击)预防:防止 XSS 攻击的关键是对用户输入的数据进行有效的过滤和转义,避免将恶意脚本注入到页面中。可以使用 HTML 标签转义,如将 < 转换为 &lt;,以及使用 CSP(Content Security Policy)策略限制页面资源加载和脚本执行。

  • CSRF(跨站请求伪造)预防:防止 CSRF 攻击的方法包括使用随机 Token、同源检测、Referer 检测、双重 Cookie 等。其中,使用随机 Token 是最常见的防御方式,即每次请求都要附带一个随机生成的 Token,并在服务器端验证 Token 的有效性。

9. typescript有哪些优势
10. 手撕promise
11. 打包工具(rollup)的使用

9. TypeScript 的优势

TypeScript 是 JavaScript 的一个超集,通过添加静态类型支持来提供更丰富的开发工具和更强大的代码结构。它的优势包括:

  1. 静态类型检查:TypeScript 提供了静态类型检查,可以在编译时发现潜在的类型错误,减少运行时错误的发生,提高代码的可靠性和可维护性。

  2. 更好的代码提示:由于 TypeScript 明确了变量的类型信息,IDE 和编辑器可以提供更准确、更丰富的代码提示和自动补全功能,提高了开发效率。

  3. 更清晰的代码结构:TypeScript 强制规定了变量、函数、方法等的类型,使得代码更加清晰易懂,降低了代码的维护成本。

  4. 增强的面向对象编程支持:TypeScript 支持类、接口、模块等面向对象编程的特性,使得代码更具可扩展性和可重用性。

  5. 更好的团队协作:静态类型检查和清晰的代码结构使得团队成员之间的协作更加高效,减少了因为代码错误而导致的沟通成本。

  6. 兼容性:TypeScript 是 JavaScript 的超集,可以与现有的 JavaScript 代码无缝集成,可以逐步迁移到 TypeScript,不需要做大的改动。

10. 手撕 Promise

以下是一个简单的手撕 Promise 的实现:

class MyPromise {
    constructor(executor) {
        this.state = 'pending';
        this.value = undefined;
        this.callbacks = [];

        const resolve = (value) => {
            if (this.state === 'pending') {
                this.state = 'fulfilled';
                this.value = value;
                this.callbacks.forEach(callback => callback.onFulfilled(value));
            }
        };

        const reject = (reason) => {
            if (this.state === 'pending') {
                this.state = 'rejected';
                this.value = reason;
                this.callbacks.forEach(callback => callback.onRejected(reason));
            }
        };

        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }

    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            const handleCallback = (callback, value) => {
                try {
                    const result = callback(value);
                    if (result instanceof MyPromise) {
                        result.then(resolve, reject);
                    } else {
                        resolve(result);
                    }
                } catch (error) {
                    reject(error);
                }
            };

            if (this.state === 'fulfilled') {
                handleCallback(onFulfilled, this.value);
            } else if (this.state === 'rejected') {
                handleCallback(onRejected, this.value);
            } else {
                this.callbacks.push({
                    onFulfilled: (value) => handleCallback(onFulfilled, value),
                    onRejected: (reason) => handleCallback(onRejected, reason)
                });
            }
        });
    }

    catch(onRejected) {
        return this.then(null, onRejected);
    }

    finally(onFinally) {
        return this.then(
            value => MyPromise.resolve(onFinally()).then(() => value),
            reason => MyPromise.resolve(onFinally()).then(() => { throw reason; })
        );
    }

    static resolve(value) {
        return new MyPromise(resolve => resolve(value));
    }

    static reject(reason) {
        return new MyPromise((_, reject) => reject(reason));
    }

    static all(promises) {
        return new MyPromise((resolve, reject) => {
            const results = [];
            let count = 0;

            promises.forEach((promise, index) => {
                MyPromise.resolve(promise).then(
                    value => {
                        results[index] = value;
                        count++;
                        if (count === promises.length) {
                            resolve(results);
                        }
                    },
                    reject
                );
            });
        });
    }

    static race(promises) {
        return new MyPromise((resolve, reject) => {
            promises.forEach(promise => {
                MyPromise.resolve(promise).then(resolve, reject);
            });
        });
    }
}

11. 打包工具(Rollup)的使用

Rollup 是一款 JavaScript 模块打包工具,类似于 Webpack,但主要用于打包库或框架。它的使用方式如下:

  1. 安装 Rollup:通过 npm 安装 Rollup。
npm install rollup --save-dev
  1. 创建配置文件:创建一个名为 rollup.config.js 的配置文件,用于配置打包的入口、输出目录、插件等信息。
// rollup.config.js

export default {
    input: 'src/main.js',
    output: {
        file: 'dist/bundle.js',
        format: 'cjs'
    }
};
  1. 编写源代码:在 src 目录下编写你的源代码。

  2. 运行 Rollup:在终端中执行 rollup 命令,开始打包。

npx rollup -c
  1. 查看输出结果:打包完成后,会在指定的输出目录中生成打包后的文件。

Rollup 支持多种插件,可以通过配置文件来引入插件,并对代码进行各种处理,例如压缩、转换 ES6+ 语法等。Rollup 的特点是输出结果更加干净、更小,适合用于打包库或框架。

13. 考不考研(不该说考的)
14. 前后端交互基本流程
15. 项目后端怎么写的
16. ajax

14. 前后端交互基本流程

前后端交互的基本流程通常包括以下几个步骤:

  1. 前端发送请求:前端页面通过 AJAX 请求或表单提交等方式向后端发送请求,请求可以是获取数据、提交表单、执行操作等。

  2. 后端接收请求:后端服务器接收到前端发送的请求,通过相应的路由或接口进行处理。

  3. 后端处理请求:后端服务器根据接收到的请求进行相应的处理,包括数据查询、业务逻辑处理、数据库操作等。

  4. 后端返回响应:后端服务器处理完请求后,将处理结果封装成响应数据返回给前端,通常以 JSON 格式返回。

  5. 前端接收响应:前端页面接收到后端返回的响应数据,根据响应数据进行相应的处理,例如更新页面内容、显示错误信息等。

  6. 前端处理响应:前端页面根据接收到的响应数据进行相应的处理,可能会根据返回的数据进行页面渲染、状态更新等操作。

这样,前后端之间通过请求和响应进行通信,实现了数据的交互和页面的更新。

16. AJAX

AJAX(Asynchronous JavaScript and XML)是一种在不重新加载整个页面的情况下,通过 JavaScript 发起 HTTP 请求并接收响应的技术。它的基本原理是通过浏览器提供的 XMLHttpRequest 对象来实现异步通信。

使用 AJAX 可以实现以下功能:

  1. 数据交互:可以在不刷新页面的情况下与服务器进行数据交互,获取数据并更新页面内容。

  2. 异步加载:可以异步加载页面的一部分内容,提高页面的加载速度和用户体验。

  3. 增量更新:可以根据用户的操作实时更新页面内容,不需要重新加载整个页面。

  4. 动态交互:可以实现动态的用户交互效果,例如自动完成、实时搜索等。

使用 AJAX 可以实现多种前端交互功能,是现代 Web 应用开发中常用的技术之一。

18. 还有什么想问的吗(腾讯云技术栈)

总结:除了vuerouter答的不好其它基本都讲出来了,不知道为啥挂了:)

作者:Cruiter
链接:www.nowcoder.com/feed/main/d…
来源:牛客网