前端面试问题(jwt/布局/vue数组下标/扁平化/菜单树形/url api/新版本)

前端面试问题(jwt/布局/vue数组下标/扁平化/菜单树形/url api/新版本)

1. jwt鉴权逻辑

前端 JWT 鉴权逻辑通常涉及在发起请求时携带 JWT,并在接收到响应后处理可能的授权问题。

1. 用户登录:

  1. 用户提供凭证: 用户在登录界面输入用户名和密码。

  2. 请求后端认证: 前端通过发送用户提供的凭证(通常是用户名和密码)到后端进行身份验证。

  3. 接收并存储Token: 如果身份验证成功,后端生成 JWT 并将其发送给前端。前端通常会将 JWT 存储在客户端(通常是浏览器)的本地存储(localStorage 或 sessionStorage)中。

2. 请求时的鉴权:

  1. 构建请求头: 在每次发送请求时,前端将存储的 JWT 添加到请求头中。

    // 使用 Axios 发送请求的方式
    const token = localStorage.getItem('jwtToken');
    axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
    
  2. 发送请求: 发送请求到后端,后端会检查请求头中的 JWT 是否有效。

  3. 处理响应: 前端接收到响应后,可以根据响应状态码和内容进行相应的处理。

    • 如果响应状态码为 401(未授权)或 403(禁止访问),可能表示 JWT 已过期或用户无权限,需要处理重新登录或其他操作。

    • 如果响应状态码为 200,表示请求成功,前端可以继续处理返回的数据。

3. 处理过期的Token:

  1. 捕获过期错误: 前端需要捕获过期错误。当后端返回 401 状态码时,可以视为 JWT 过期。

  2. 刷新Token: 如果服务器支持,可以尝试使用 refresh token 来获取新的 JWT,避免用户重新登录。

注意事项:

  • 安全存储: JWT 存储在前端,因此需要确保它被安全地存储。一般来说,避免将敏感信息存储在 JWT 中,因为它可以被解码。

  • 定期刷新: 定期检查 JWT 是否过期,如果过期,需要进行刷新操作。

  • 前端安全性: 前端只能负责存储和传递 JWT,实际的用户身份验证和授权逻辑仍然应该由后端负责。

2. 实现顶部导航+左侧菜单+右侧主内容区域布局

在前端,实现顶部导航、左侧菜单、右侧主内容区域布局通常有多种方式,取决于项目的需求和开发者的技术偏好。以下是其中三种常见的实现方式:

1. Flexbox 布局:

使用 CSS 的 Flexbox 布局是一种简单而灵活的方法,它能够轻松地实现顶部导航、左侧菜单和右侧主内容区域的布局。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Flexbox Layout</title><style>body {margin: 0;display: flex;flex-direction: column;height: 100vh;}header, main {flex: 0 0 auto;}main {display: flex;}nav {width: 200px;background-color: #333;color: #fff;}section {flex: 1;padding: 20px;}</style>
</head>
<body><header><!-- 顶部导航 --><h1>顶部</h1></header><main><nav><!-- 左侧菜单 --><h1>左侧</h1></nav><section><!-- 右侧主内容区域 --><h1>右侧</h1></section></main>
</body>
</html>

2. Grid 布局:

CSS Grid 布局也是一种强大的布局方式,允许更复杂的网格结构。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Grid Layout</title><style>body {margin: 0;display: grid;grid-template-columns: 200px 1fr;grid-template-rows: auto 1fr;grid-template-areas:"header header""nav main";height: 100vh;}header, nav, main {padding: 20px;}header {grid-area: header;background-color: #ddd;}nav {grid-area: nav;background-color: #333;color: #fff;}main {grid-area: main;display: flex;}</style>
</head>
<body><header><!-- 顶部导航 --><h1>顶部</h1></header><nav><!-- 左侧菜单 --><h1>左侧</h1></nav><main><!-- 右侧主内容区域 --><h1>右侧</h1></main>
</body>
</html>

3. Bootstrap:

使用 Bootstrap 框架是一种快速搭建响应式布局的方法。Bootstrap 提供了许多现成的组件和样式,使得实现这种布局变得非常容易。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"><title>Bootstrap Layout</title>
</head>
<body><header class="bg-light p-3"><!-- 顶部导航 --><h1>顶部</h1></header><div class="container-fluid"><div class="row"><nav class="col-md-2 bg-dark text-light"><!-- 左侧菜单 --><h1>左侧</h1></nav><main class="col-md-10"><!-- 右侧主内容区域 --><h1>右侧</h1></main></div></div>
</body>
</html>

4. CSS Float 布局

使用float属性可以实现一种简单的布局,但需要注意清除浮动以避免影响后续布局。

<div class="header">顶部导航</div>
<div class="menu">左侧菜单</div>
<div class="content">右侧主内容区域</div><style>.header { clear: both; }.menu { float: left; width: 20%; }.content { margin-left: 20%; }
</style>

3. Vue数组下标改值时响应式丢失,为什么

在Vue中,数组下标改值导致响应式丢失的原因通常是由于Vue对数组的监听机制的限制。Vue的响应式系统对于数组的变更检测有一些局限性,主要涉及到以下情况:

  1. 直接通过索引设置数组元素时,无法触发视图更新: Vue的响应式系统不能检测到直接通过索引设置数组元素的变化。例如,array[index] = value 这种方式不会触发响应式更新。

  2. 通过splice方法添加或删除元素时能够触发更新: 使用Vue提供的数组变异方法(例如splice)来添加或删除元素时,Vue能够监听到变化并触发相应的更新。

// 在Vue组件中的data
data() {return {myArray: [1, 2, 3]};
},
methods: {updateValue() {// 这种方式修改数组的元素,不会触发响应式更新this.myArray[0] = 99;}
}

直接通过索引修改数组元素的值 this.myArray[0] = 99; 不会触发Vue的响应式系统。

为了确保能够触发响应式更新,可以使用Vue提供的变异方法,比如使用Vue.set方法:

methods: {updateValue() {// 使用 Vue.set 来确保触发响应式更新Vue.set(this.myArray, 0, 99);}
}

或者使用splice方法:

methods: {updateValue() {// 使用 splice 来确保触发响应式更新this.myArray.splice(0, 1, 99);}
}

4. 数组扁平化

  1. 使用递归(原生 JavaScript):

    function flattenArray(arr) {return arr.reduce((acc, curr) => Array.isArray(curr) ? acc.concat(flattenArray(curr)) : acc.concat(curr), []);
    }const nestedArray = [[0, 1], [2, [3, 4]], [5, 6]];
    const flattenedArray = flattenArray(nestedArray);
    console.log(flattenedArray);
    
  2. 使用 Array.flat() 方法(ECMAScript 2019):

    const nestedArray = [[0, 1], [2, [3, 4]], [5, 6]];
    const flattenedArray = nestedArray.flat(Infinity);
    console.log(flattenedArray);
    
  3. 使用 lodash 库:

    const _ = require('lodash');const nestedArray = [[0, 1], [2, [3, 4]], [5, 6]];
    const flattenedArray = _.flattenDeep(nestedArray);
    console.log(flattenedArray);
    

Array.flat() 方法和 lodash 的 _.flattenDeep() 都可以递归地将数组扁平化,而原生的递归方法Array.reduce()` 方法需要手动处理递归。

5. 菜单数组转换为嵌套树形结构

[{ id: 1, menu: '水果', level: 1 }, { id: 2, menu: '橘子', level: 2, parentId: 1 } ]
[{ id: 1, menu: '水果', level: 1, children: [{ id: 2, menu: '橘子', level: 2, parentId: 1 }] }]
function convertToNestedTree(menuArray) {const idToMenuMap = {}; // 用于存储菜单项的映射,通过id快速查找// 构建映射menuArray.forEach(item => {idToMenuMap[item.id] = item;});// 构建树形结构const tree = [];menuArray.forEach(item => {if (!item.parentId) {// 如果没有parentId,说明是根节点,直接添加到树中tree.push(item);} else {// 如果有parentId,将当前项添加到父级的children数组中const parentMenu = idToMenuMap[item.parentId];if (parentMenu) {if (!parentMenu.children) {parentMenu.children = [];}parentMenu.children.push(item);}}});return tree;
}const menuArray = [{ id: 1, menu: '水果', level: 1 },{ id: 2, menu: '橘子', level: 2, parentId: 1 },];const nestedTree = convertToNestedTree(menuArray);
console.log(nestedTree);//[{ id: 1, menu: '水果', level: 1, children: [{ id: 2, menu: '橘子', level: 2, parentId: 1 }] }]

6. url 参数获取的 API

在前端,使用 URLSearchParams 对象来获取 URL 参数。这是一个原生 JavaScript 对象,可用于解析 URL 查询参数。

// 假设 URL 为 https://example.com/page?name=John&age=25const urlParams = new URLSearchParams(window.location.search);// 获取单个参数
const name = urlParams.get('name'); // 返回 'xx'
const age = urlParams.get('age');   // 返回 '25'// 获取所有参数
const allParams = {};
urlParams.forEach((value, key) => {allParams[key] = value;
});console.log(allParams);
// 输出:{ name: 'xx', age: '25' }

使用 URLSearchParams 对象从当前页面的 URL 中提取参数。

7. 新版本发布后,怎么用技术手段通知用户刷新页面

在前端中,可以使用以下几种技术手段来通知用户刷新页面以加载新版本:

  1. Service Worker 和 Cache 更新:

    • 使用 Service Worker 来缓存资源并控制页面加载。
    • 当新版本发布时,Service Worker 可以检测到更新,然后发送消息到页面,通知用户有新版本可用。
    • 页面收到消息后,可以显示一个通知或提示,引导用户刷新页面。
  2. WebSocket 或 Server-Sent Events (SSE):

    • 使用 WebSocket 或 SSE 与服务器建立实时通信通道。
    • 当新版本发布时,服务器通过通道向客户端发送消息。
    • 客户端收到消息后,可以显示通知并提示用户刷新页面。
  3. Polling:

    • 定期向服务器发起请求检查是否有新版本。
    • 当服务器检测到新版本时,返回相应的信息。
    • 页面收到信息后,显示通知并引导用户刷新页面。
  4. LocalStorage 或 IndexedDB 标记:

    • 在本地存储(LocalStorage)或 IndexedDB 中保存一个标记,表示当前页面的版本。
    • 当新版本发布时,将新版本的标记写入本地存储或 IndexedDB。
    • 页面加载时检查标记,如果检测到新版本,显示通知并引导用户刷新页面。
  5. 使用 Service Worker 的 skipWaitingclients.claim

    • 在 Service Worker 中使用 self.skipWaiting()clients.claim() 来立即激活新版本的 Service Worker。
    • 在新版本的 Service Worker 中发送消息到页面,通知用户有新版本可用。
    • 页面接收到消息后,显示通知并引导用户刷新页面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/696103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用Docker部署MongoDB并结合内网穿透实现远程访问本地数据库

文章目录 前言1. 安装Docker2. 使用Docker拉取MongoDB镜像3. 创建并启动MongoDB容器4. 本地连接测试5. 公网远程访问本地MongoDB容器5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定TCP地址远程访问 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 …

2024最佳住宅代理IP服务商有哪些?

跨境出海已成为了近几年的最热趋势&#xff0c;大批量的企业开始开拓海外市场&#xff0c;而海外电商领域则是最受欢迎的切入口。新兴的tiktok、Temu&#xff0c;老牌的Amazon、Ebay&#xff0c;热门的Etsy、Mecari等等都是蓝海一片。跨境入门并不难&#xff0c;前期的准备中不…

深入理解文件查看命令:cat、more、less、tail、head

在Linux系统中&#xff0c;有许多命令用于查看文件的内容&#xff0c;其中包括cat、more、less、tail和head。这些命令提供了不同的方式来浏览文本文件&#xff0c;适用于各种查看需求。在本篇博客中&#xff0c;我们将深入介绍这些命令&#xff0c;并通过示例演示它们的用法。…

Spring Boot打war包部署到Tomcat,访问页面404 !!!

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 Spring Boot打war包部署到Tomcat&#xff0c;访问页面404 &#xff01;&#xff01;&#xff01;解决办法&#xff1a;检查Tomcat版本和Jdk的对应关系&#xff0c;我的Tomcat是6.x&#x…

Sping基础篇----掌握Sping的控制反转/依赖注入的概念【实战案例总结】

作为一名对技术充满热情的学习者&#xff0c;我一直以来都深刻地体会到知识的广度和深度。在这个不断演变的数字时代&#xff0c;我远非专家&#xff0c;而是一位不断追求进步的旅行者。通过这篇博客&#xff0c;我想分享我在某个领域的学习经验&#xff0c;与大家共同探讨、共…

SMMU介绍

SMMU&#xff08;System Memory Management Unit&#xff09;是一种硬件设备&#xff0c;其作用是在虚拟地址空间和物理地址空间之间提供地址转换的功能。它通常用于处理虚拟化环境中的 I/O 设备&#xff0c;例如虚拟机中的设备访问或者容器环境中的设备隔离。 SMMU 的主要作用…

KVM虚拟机的克隆方式

话不多说&#xff0c;直接上操作 首先确定我们要克隆的模板机器&#xff0c;这样可以方便我们后续克隆许多机器 IP获取最好就是dhcp模式&#xff0c;这样克隆出来的机器就不需要自己再去改ip了 确定需要克隆的模板机以后&#xff0c;先关机再执行克隆操作 virsh shutdown ser…

【SiamFC】《Fully-Convolutional Siamese Networks for Object Tracking》

ECCV 2016 Workshops 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method5 Experiments5.1 Datasets and Metrics5.2 The OTB-13 benchmark5.3 The VOT benchmarks5.4 Dataset size 6 Conclusion&#xff08;own&#xff09;/ Future wo…

Android系统启动流程

android的启动流程是从底层开始进行的&#xff0c;具体如下所示&#xff1a; Android是基于Linux内核的系统&#xff0c;Android的启动过程主要分为两个阶段&#xff0c;首先是Linux内核的启动&#xff0c;然后是Android框架的启动。 可以将Andorid系统的启动流程分为以下五个…

【QT 5 +Linux下软件桌面快捷方式+qt生成软件创建桌面图标+学习他人文章+第二篇:编写桌面文件.desktop】

【QT 5 Linux下软件桌面快捷方式qt生成软件创建桌面图标学习他人文章第二篇&#xff1a;编写桌面文件.desktop】 1、前言2、实验环境3、自我学习总结-本篇总结1、新手的疑问&#xff0c;做这件事目的2、了解.desktop3、三个关键目录以及文件编写1、目录&#xff1a;/opt/2、目录…

【鸿蒙 HarmonyOS 4.0】开发工具安装

一、准备开发环境 1.1、安装IDE 鸿蒙应用开发需要使用配套的IDE——HUAWEI DevEco Studio。 DevEco Studio基于IntelliJ IDEA Community&#xff08;IDEA社区版&#xff09;构建&#xff0c;为鸿蒙应用提供了一站式开发环境&#xff0c;集成了开发、运行、调试以及发布应用的…

【leetcode刷题之路】面试经典150题(3)——哈希表+区间

文章目录 5 哈希表5.1 【哈希表】赎金信5.2 【数学】同构字符串5.3 【数学】单词规律5.4 【哈希表】有效的字母异位词5.5 【哈希表】字母异位词分组5.6 【双指针】两数之和5.7 【数学】快乐数5.8 【哈希表】219. 存在重复元素 II5.9 【数学】最长连续序列 6 区间6.1 【数学】汇…

Stable Diffusion 模型分享:AstrAnime(Astr动画)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五 下载地址 模型介绍 AstrAnime 是一个动漫模型&#xff0c;画风色彩鲜明&#xff0c;擅长绘制漂亮的小姐姐。 条目内容类型大模型…

fastjson解析自定义get方法导致空指针问题

背景 为了在日志中把出入参打印出来&#xff0c;以便验证链路和排查问题&#xff0c;在日志中将入参用fastjson格式化成字符串输出&#xff0c;结果遇到了NPE。 问题复现 示例代码 public static void main(String[] args) {OrganizationId orgId new OrganizationId();N…

规模化强化学习 — 多任务强化学习

1 简述 1.1 单任务强化学习&#xff08;STRL&#xff09; 在单任务强化学习中&#xff0c;一个无人机的AI系统可能被训练来执行特定的任务&#xff0c;比如自主导航。在这个任务中&#xff0c;无人机需要学习如何有效地从起点飞行到终点&#xff0c;并避开障碍物。 举例&#…

【Java多线程】分析线程加锁导致的死锁问题以及解决方案

目录 1、线程加锁 2、死锁问题的三种经典场景 2.1、一个线程一把锁 2.2、两个线程两把锁 2.3、N个线程M把锁&#xff08;哲学家就餐问题&#xff09; 3、解决死锁问题 1、线程加锁 其中 locker 可以是任意对象&#xff0c;进入 synchronized 修饰的代码块, 相当于加锁&…

Java SourceDataLine 播放音频

Java SourceDataLine 播放音频 1 依赖2 接口3 实现4 测试 项目Value音频格式 添加依赖*.wav(JDK 原生支持)*.pcm(JDK 原生支持)*.au(JDK 原生支持)*.aiff(JDK 原生支持)*.mp3mp3spi.jar*.flacjflac-codec.jar 1 依赖 <dependency><groupId>com.googlecode.soundl…

⭐北邮复试刷题LCR 052. 递增顺序搜索树__DFS (力扣119经典题变种挑战)

LCR 052. 递增顺序搜索树 给你一棵二叉搜索树&#xff0c;请 按中序遍历 将其重新排列为一棵递增顺序搜索树&#xff0c;使树中最左边的节点成为树的根节点&#xff0c;并且每个节点没有左子节点&#xff0c;只有一个右子节点。 示例 1&#xff1a; 输入&#xff1a;root [5,…

DataX - 全量数据同步工具

前言 今天是2024-2-21&#xff0c;农历正月十二&#xff0c;相信今天开始是新的阶段&#xff0c;尽管它不是新的周一、某月一日、某年第一天&#xff0c;尽管我是一个很讲究仪式感的人。新年刚过去 12 天&#xff0c;再过 3 天就开学咯&#xff0c;开学之后我的大学时光就进入了…

TypeScript01:安装TypeScript

一、TypeScript 官方网站&#xff1a;https://www.tslang.cn/docs/index.html 练习场&#xff1a;https://www.typescriptlang.org/zh/play 好处&#xff1a; 强类型语言&#xff0c;对JS弱类型的一个良好补充&#xff1b;TS利于大型项目团队合作&#xff0c;可以一定程度…