大前端
单点登录是是什么, 具体流程是什么
- 用户访问应用 A
- 应用 A 发现用户未登录,重定向到单点登录服务器。
- 在 SSO 服务器上进行登录操作,输入用户名和密码等凭证。
- SSO 服务器验证用户登录信息。
- 验证通过后,SSO 服务器创建一个全局令牌(token)。
- 返回令牌给应用 A
- 应用 A 验证令牌
- 用户访问应用 A 资源
- 当用户后续访问其他信任该 SSO 服务器的应用 B 时,应用 B 会从 SSO 服务器获取令牌并验证。
- 验证通过后,用户可以在应用 B 中访问资源,无需再次登录。
前端如何进⾏权限管理的
接⼝级权限:
通过登录判断⽤⼾登记,根据各⾃的⻆⾊向后台获取⻚⾯url,前端根据url进⾏⻚⾯渲染,有权限的显⽰,⽆权限的不显⽰。
⻚⾯级权限:
⻚⾯及权限,定义一个权限和页面的映射关系,然后使用前置路由守卫去做处理。
SSR 的优点包括:
- 更快的首屏加载速度:由于服务器端已经生成了完整的 HTML 页面,客户端浏览器可以更快地显示页面内容,减少了客户端的渲染时间。
- 更好的 SEO 优化:搜索引擎爬虫可以直接获取服务器端生成的 HTML 页面,有利于搜索引擎对页面内容的理解和索引,提高了网站的搜索引擎排名。
- 提升用户体验:用户可以更快地看到页面内容,减少了等待时间,提高了用户体验。
然而,SSR 也存在一些挑战和注意事项:
- 服务器端的性能要求:服务器需要处理更多的请求和渲染工作,对服务器的性能有一定的要求。
- 开发复杂度增加:需要同时考虑服务器端和客户端的开发,增加了开发的复杂度。
- 数据获取和同步:在服务器端渲染时,需要确保获取的数据在客户端和服务器端保持一致,避免出现数据不一致的情况。
- 缓存策略:需要合理设置缓存策略,以提高性能和减少服务器的负载。
封装组件:什么情况封装、如何让组件变得更加通用?封装的时候需要注意什么?
-
什么情况下封装组件:逻辑重复、独立性:功能封装在组件中,可以使组件具有更好的独立性和可维护性、复杂逻辑:如果某个功能或逻辑比较复杂,将其封装为一个组件可以使代码更易于理解和管理。
-
如何让组件变得更加通用:定义明确的接口、参数化、可扩展性、分离关注点、文档化
-
封装时需要注意什么:单一职责原则、命名规范、测试、兼容性、性能
前端项目优化
- 代码优化:
- 减少 JavaScript 代码的体积和复杂度
- 使用 tree shaking、code splitting 等技术去除无用代码
- 优化 CSS 文件的大小和结构
- 使用 gzip 或 Brotli 压缩静态资源
- 压缩html : html-minfy-loader
- 图片压缩 url-loader
- 资源优化:
- 使用图片、字体等资源的最佳格式(如 WebP、WOFF2)
- 实现图片懒加载和视频预加载
- 使用 CDN 加速静态资源的传输
- 设置合理的缓存策略
- 性能优化:
- 减少 DOM 操作,使用虚拟 DOM 技术
- 使用 Web Worker 和 Service Worker 异步处理耗时任务
- 优化页面初次加载和后续页面切换的速度
- 用户体验优化:
- 实现骨架屏和占位符,提升感知性能
- 使用 PWA 技术提升离线体验和增量更新
- 优化页面滚动、点击等交互体验
- 提升页面的可访问性
- 监控和持续优化:
- 使用性能监控工具(如 Lighthouse、PageSpeed Insights)定期评估页面性能
- 收集用户行为数据,分析优化点
- 建立自动化的优化流程,持续优化项目
mvvm和mvc区别
- 组件职责分工:
- MVC 模式中,Model 负责数据和业务逻辑,View 负责界面显示,Controller 负责处理用户输入并更新 Model 和 View。
- MVVM 模式中,Model 同样数据和业务逻辑,View 负责界面显示,ViewModel 负责处理 Model 和 View 之间的通信。
- 视图和控制器的关系:
- MVC 中,View 和 Controller 是紧耦合的,Controller 直接操作 View 的渲染。
- MVVM 中,ViewModel 与 View 是松耦合的,ViewModel 通过数据绑定与 View 进行交互,View 只负责渲染。
- 数据流向:
- MVC 中,数据流向是单向的
- MVVM 中,数据流向是双向的:
- 可测试性:
- MVC 中,Controller 通常很难测试,因为它同时依赖于 Model 和 View。
- MVVM 中,ViewModel 可以独立于 View 进行测试,因为它不依赖于 View 的具体实现。
前端开发模式进化史
- 静态网页阶段 (1990s):
- 这个阶段主要以静态 HTML 页面为主,页面内容和样式都写在同一个文件中。
- 交互性很弱,大多数功能都需要依赖后端服务来实现。
- 动态网页阶段 (2000s):
- 随着 JavaScript 的出现,前端开发者可以在浏览器端实现一些简单的交互效果。
- 出现了服务器端渲染 (Server-Side Rendering, SSR) 的模式,后端负责生成 HTML 页面并返回给客户端。
- 单页应用 (SPA) 阶段 (2010s):
- 为了实现更丰富的交互体验,出现了基于 JavaScript 框架/库的单页应用 (SPA) 模式。
- 前端负责管理页面状态和交互逻辑,后端提供 API 接口服务。
- 代表框架/库有 React、Vue.js、Angular 等。
- 全栈开发阶段 (2010s 至今):
- 前端开发者逐渐需要掌握后端技术,成为全栈开发者。
- 出现了 Node.js 等基于 JavaScript 的后端运行时,前后端可以共享代码。
- 前端框架也开始整合后端服务,形成了 "全栈框架",如 Next.js、Nuxt.js 等。
- 微前端 (Micro-Frontend) 阶段 (2010s 至今):
- 为了解决大型 SPA 应用的复杂度问题,出现了微前端架构。
- 将应用划分为多个独立的微前端模块,各模块可以独立开发、部署和维护。
- 代表框架/方案有 single-spa、Module Federation 等。
- 低代码/no-code 阶段 (2010s 至今):
- 为了降低前端开发的门槛,出现了各种低代码/no-code 平台。
- 开发者可以通过拖拽组件、配置参数等方式快速构建应用。
- 代表平台有 Bubble、Appian、Outsystems 等。
前端工程化解决什么问题
- 模块化、组件化帮助管理和维护代码
- 构建和部署
- 前端项目需要进行编译、打包、压缩等构建操作,然后部署到服务器上。
- 前端工程化引入了构建工具(如 Webpack、Gulp、Rollup)和部署流程,提高了构建和部署的效率。
- 开发环境和工具链
- 前端开发需要使用各种工具和框架,如 JavaScript 编译器、CSS 预处理器、测试框架等。
- 前端工程化集成了这些工具,形成了一套标准的开发工具链,提高了开发效率。
- 依赖管理
- 前端项目通常依赖大量的第三方库和框架,需要有统一的依赖管理机制。
- 前端工程化引入了包管理器(如 npm、yarn)和依赖锁定机制,方便团队协作和版本控制。
- 质量保证
- 为了保证代码质量,需要引入单元测试、端到端测试、持续集成等自动化测试机制。
- 前端工程化提供了测试框架和 CI/CD 工具,确保代码质量和交付速度。
- 跨环境兼容
- 前端需要考虑不同浏览器、设备、操作系统的兼容性问题。
- 前端工程化引入了自动化的兼容性处理方案,如 Polyfill、Autoprefixer 等。
尾递归有什么用
避免栈溢出:由于尾递归可以将递归调用转换为迭代,编译器会将尾递归转化为迭代
js变量提升的好处
- 提前声明变量:变量提升允许你在代码的任何位置使用变量,即使变量的声明在后面。这意味着你可以在代码的其他部分引用尚未声明的变量,而不会导致错误。
- 提高代码的可读性:变量提升可以使代码更具可读性,因为你可以在使用变量之前先声明它,这有助于理解变量的作用域和用法。
- 避免错误:变量提升可以避免一些常见的错误,例如在变量未声明之前就使用它,或者在变量声明之前就对其进行赋值。
- 提高代码的效率:变量提升可以在代码执行之前就为变量分配内存,这有助于提高代码的执行效率。
打开一个页面可以做那些操作减少请求?
- 资源合并和压缩:
- 合并 CSS 和 JavaScript 文件,减少 HTTP 请求数。
- 压缩 CSS、JavaScript 和图片等资源文件,减小文件大小。
- 使用 CDN (内容分发网络):
- 将静态资源(如 CSS、JavaScript、图片等)部署到 CDN 服务器上,利用 CDN 的就近分发特性,减少访问延迟。
- 延迟加载和懒加载:
- 采用延迟加载或懒加载技术,只在需要时再加载资源,减少初次加载时的请求量。
- 例如,页面滚动到某个位置时再加载图片资源。
- 缓存策略优化:
- 对于静态资源,设置合理的 HTTP 缓存头,利用浏览器缓存减少重复请求。
- 对于动态资源,合理使用 Etag 或 Last-Modified 头,实现增量更新。
- 服务端渲染 (SSR) 或静态站点生成 (SSG):
- 利用 Server-side Rendering (SSR) 或 Static Site Generation (SSG) 技术,在服务端预渲染页面,减少客户端的请求数量。
- HTTP/2 或 HTTP/3 优化:
- 使用 HTTP/2 或 HTTP/3 协议,利用其多路复用、头部压缩等特性,减少 TCP 连接开销。
- 图片优化:
- 根据实际需求,选择合适的图片格式(如 WebP、AVIF)和压缩方式,减小图片文件大小。
- 使用
srcset
和sizes
属性,根据设备屏幕大小提供合适尺寸的图片。
- 骨架屏/预加载:
- 使用骨架屏技术,在资源加载完成前展示简单的占位元素,提升用户体验。
- 使用
<link rel="preload">
预加载关键资源,减少关键渲染路径的阻塞时间。
- API 优化:
- 对于 API 请求,可以采用批量请求、增量更新等方式,减少API调用次数。
- 对于不经常变化的数据,可以设置适当的缓存时间。
前端项⽬中有哪些性能瓶颈?如何诊断和解决这些问题?
• 性能诊断⼯具:使⽤Chrome DevTools、Lighthouse或WebPageTest等⼯具进⾏性能评估。
• 代码分割和懒加载:通过动态导⼊( import() )实现代码分割和懒加载,减少初始加载时间。
• 优化图⽚和资源:压缩图⽚和使⽤现代格式(如WebP),并合理利⽤缓存策略。
• 减少重绘和回流:优化CSS属性(避免使⽤导致回流的属性),并使⽤ transform 和 opacity进⾏动画处理,这些属性不会触发回流。
• 使⽤Web Workers:对于复杂的数据处理,使⽤Web Workers将⼯作从主线程中移出,避免界⾯卡顿。
描述⼀次重⼤的前端故障,你是如何定位和解决问题的?
前端故障处理流程的例⼦:
• 问题:⽤⼾报告⽹站在特定⻚⾯上加载异常缓慢。
• 定位问题:
a. 性能分析:使⽤Chrome DevTools的Performance tab记录并分析⻚⾯加载时的性能。
b. 查看资源加载:检查Network tab以确认是否有资源加载缓慢或失败。
c. JavaScript性能分析:使⽤JavaScript Profiler查看是否有函数执⾏时间过⻓。
d. 代码审查:审查相关代码,检查是否有性能不佳的操作,如在循环中执⾏复杂的DOM操作。
• 解决问题:
a. 优化图⽚:发现⼀些⼤图⽚未被优化。使⽤压缩⼯具减少图⽚⼤⼩,并转换为更⾼效的格式
(如WebP)。
b. 代码优化:在JavaScript中发现不必要的重复DOM查询和更新。通过缓存DOM引⽤和减少DOM
操作来优化代码。
c. 延迟加载:对⾮关键资源实施懒加载,以加快⾸次加载速度。
• 后续:在解决问题后,通过内部代码审查和性能监控⼯具持续监控⽹站性能,预防未来的性能问题。
你如何看待前端开发中的⽆障碍(Accessibility)?
确保所有⽤⼾,包括残疾⼈,都能使⽤和访问Web内容和应⽤的实践。⽆障碍不仅是道德责任,也常常是法律要求。
• 重要性:
◦ 包容性:⽆障碍设计提⾼了⽹站的包容性,确保所有⼈都能平等地访问信息和服务。◦ SEO:改善⽆障碍性也可以提⾼搜索引擎优化(SEO),因为⽆障碍优化的许多⽅⾯(如语义
HTML)也对搜索引擎友好。
• 实践⽅法:
a. 语义化的HTML:使⽤正确的HTML元素对内容进⾏标记。
b. 键盘可访问性:确保所有功能都可以通过键盘操作。
c. 屏幕阅读器优化:确保所有内容都可以被屏幕阅读器正确读取。
d. 颜⾊对⽐度:确保⽂本和背景之间有⾜够的对⽐度。
e. 表单标签:确保所有表单元素都有明确的标签。
前端表格展示的数据操作5000怎么优化
-
分页和滚动时动态加载下一页
-
数据预处理与缓存
- 在服务端或构建时对数据进行预处理,如排序、过滤等操作。
- 将预处理后的数据缓存在客户端,减少重复计算的开销。
-
UI 优化
- 优化表格 UI 的复杂度,减少不必要的样式和交互。
- 使用 CSS 技术如
contain
属性来限制表格的渲染范围。 - 采用 Skeleton Loading 等占位技术,提升用户体验。
-
框架优化
-
增量更新
- 对于数据的增量更新,可以只更新变化的部分,而不是全部重新渲染。
- 可以配合分页或虚拟滚动,进一步优化更新性能。
开发一个前端项目怎么设计
- 需求分析
- 充分了解项目的业务需求和用户需求,确定产品的核心功能和主要场景。
- 可以采用用户故事、用例图等方式来描述需求。
- 技术选型
- 根据项目的需求和团队的技术栈,选择合适的前端框架/库,如 React、Vue.js、Angular 等。
- 确定是否需要使用 TypeScript,以及选择合适的 UI 组件库和其他辅助库。
- 架构设计
- 确定整体的前端架构,如单页应用(SPA)、多页应用(MPA)或服务端渲染(SSR)。
- 设计组件树和模块划分,确定组件的嵌套关系和数据流向。
- 设计路由结构和状态管理方案。
- 界面设计
- 根据产品需求,设计符合用户体验的界面布局和交互。
- 确定视觉风格,包括颜色、字体、图标等。
- 可以使用原型设计工具如 Figma、Sketch 等来完成界面设计。
- 开发规范
- 制定代码风格、命名规范、提交规范等开发规范,确保团队协作的一致性。
- 选择合适的模块化方案,如 CommonJS、ES6 模块等。
- 确定打包工具,如 Webpack、Rollup 等,并设置合理的配置。
- 构建工具
- 选择合适的构建工具,如 npm script、Gulp、Jenkins 等,自动化构建、测试、部署流程。
- 配置持续集成/持续部署(CI/CD)流程,提高开发效率。
- 测试策略
- 制定单元测试、组件测试、端到端测试等测试方案,确保代码质量。
- 考虑使用 Jest、Enzyme、Cypress 等测试框架。
- 性能优化
- 分析应用的性能瓶颈,如加载时间、页面渲染、网络请求等。
- 采取相应的优化措施,如代码分割、懒加载、缓存、服务端渲染等。
- 部署方案
- 确定应用的部署方式,如静态站点托管、容器部署、云服务等。
- 考虑多环境部署,如开发、测试、生产等。
- 持续迭代
- 建立完善的需求收集、反馈、迭代机制,持续优化产品。
- 关注用户反馈,及时修复 bug 并迭代新功能。
浏览器有哪些进程
- 浏览器主进程(Browser Process) 管理浏览器的用户界面、地址栏、书签、前进和后退按钮等。它还负责处理不可见的后台任务,如网络请求、文件访问和跨进程通信
- 渲染进程(Renderer Process)渲染进程负责处理浏览器标签页中的内容。
- 插件进程(Plugin Process)对于使用插件(如 Flash Player)的浏览器,每个插件实例通常运行在独立的进程中。
- GPU 进程(GPU Process)GPU 进程负责处理浏览器中的图形任务,如 2D 和 3D 绘图。它将渲染进程的绘图命令转换为 GPU 可以理解的格式,并发送给 GPU 执行。
- 网络进程(Network Process) 网络进程负责处理网络请求,如 HTTP 请求。它负责管理网络连接、缓存和安全检查。
- 存储进程(Storage Process) 存储进程负责处理文件系统访问和数据库操作,如 IndexedDB、LocalStorage 和 Cookies。
- 扩展进程(Extension Process) 对于安装了扩展的浏览器,每个扩展通常运行在自己的进程中。这样可以隔离扩展代码,防止扩展崩溃影响到浏览器的其他部分
- 服务进程(Service Worker Process)用于实现离线缓存、后台同步等功能。
浏览器运行的一些机制和原理
- 渲染引擎
- 解析HTML、CSS并将其渲染成可视化的页面
- 主要包括:解析器、DOM树构建、样式计算、布局计算、绘制等环节
- JavaScript引擎
- 负责解释执行JavaScript代码
- 主要包括:语法分析、解释执行、内存管理等
- 事件循环(Event Loop)
- 负责协调JavaScript的单线程执行
- 不断检查任务队列,按照先进先出的顺序执行任务
- 包括:同步任务、微任务、宏任务等执行机制
- 跨域访问控制(CORS)
- 浏览器为了安全会限制跨域资源的访问
- 通过设置响应头来允许或拒绝跨域请求
- 服务器端需要配合浏览器进行跨域访问控制
- 缓存机制
- 浏览器会缓存一些静态资源,如图片、CSS、JavaScript等
- 通过设置HTTP头部信息控制缓存策略
- 可以提高页面加载速度,减轻服务器压力
- 浏览器扩展(插件)
- 浏览器提供一些扩展机制,允许开发者开发插件
- 插件可以增强浏览器的功能,如广告拦截、密码管理等
- 每个浏览器的扩展机制略有不同
- 沙箱机制
- 浏览器为了安全会将网页运行在一个沙箱环境中
- 网页无法访问本地文件系统或其他敏感资源
- 通过沙箱机制可以有效防范XSS、CSRF等攻击
高级工程化
代码组织与架构:
- 采用模块化、组件化的设计,实现高内聚、低耦合的代码结构,便于维护和扩展。
- 设计合理的分层架构,如数据层、业务逻辑层、表示层等。
自动化测试:
- 全面的单元测试、集成测试、端到端测试等,以确保代码质量和稳定性。
- 持续集成和持续部署(CI/CD)中的测试自动化,及时反馈问题。
构建与部署:
- 高效的构建系统,包括代码编译、打包优化等。
- 自动化部署流程,实现一键部署到不同环境。
- 容器化技术(如 Docker)的应用,提高部署的灵活性和可移植性。
性能优化:
- 代码级别的性能优化,如算法改进、内存管理优化。
- 网络性能优化,包括减少请求次数、优化数据传输等。
- 资源加载策略优化,提升页面加载速度。
监控与预警:
- 对系统运行状态、性能指标等进行实时监控。
- 建立有效的预警机制,以便及时发现和处理问题。
安全工程:
- 加强代码安全性,防止常见的安全漏洞。
- 数据加密、认证授权等机制的完善。
团队协作与流程:
- 建立高效的开发流程和协作机制,如敏捷开发。
- 使用项目管理工具和代码管理工具(如 Git),提高团队协作效率。
可扩展性与灵活性:
- 设计易于扩展的系统架构,以适应业务增长和变化。
- 灵活的配置管理,方便进行不同场景下的定制
如何看待小程序,它的技术原理是?
小程序是一种不需要下载安装即可使用的应用。
以下几个方面:
- 基于Web技术,但它也能够调用手机的原生功能
- 开发者可以利用现有的Web开发知识和工具来创建小程序。
- 小程序的代码在发布前需要经过编译和打包,转换成平台可以识别的格式。
- 小程序运行在一个隔离的环境中,这个环境提供了小程序运行所需的API和组件,同时保证了小程序的安全性和性能。
- 小程序的更新是通过云端进行的,开发者发布新版本后,用户在下次打开小程序时会自动加载最新版本,无需手动更新。
小程序为什么会有两个线程?
以微信小程序为例,它使用了“双线程模型”:
- 渲染层(View层):负责展示用户界面,运行在微信的内置浏览器中,使用了类似于Web技术的WXML和WXSS。
- 逻辑层(App Service层):负责处理业务逻辑和数据,运行在微信的JavaScript引擎中,可以调用小程序提供的API进行网络请求、数据存储等操作。
说出5中web安全漏洞及防御措施
- XSS(跨站脚本攻击):对用户输入进行转义或使用 CSP。
- CSRF(跨站请求伪造):使用 CSRF Token。
- SQL 注入:使用参数化查询。
- 点击劫持:使用
X-Frame-Options
。 - 信息泄露:避免在客户端存储敏感信息。
设计一个协同文档的技术流程
-
确定目标用户群体,使用场景和功能
-
系统架构设计
-
前端:设计用户界面,包括文档编辑器、实时预览、用户交互元素等。
-
后端:设计服务器架构,包括API服务、数据库、文件存储等。
-
实时同步:设计实时数据同步机制,如WebSocket、Operational Transformation (OT) 或 Conflict-free Replicated Data Types (CRDTs)。
-
权限管理:设计用户认证和授权机制,确保文档的安全性。
-
-
数据模型设计
-
定义文档的数据结构,包括文本、格式、图片等。
-
设计用户和权限的数据模型。
-
设计版本控制和历史记录的数据模型。
-
-
实时编辑功能实现
-
实现一个编辑器前端,支持文本输入、格式化、图片插入等。
-
实现后端逻辑,处理编辑操作并广播给其他用户。
-
实现冲突解决机制,处理并发编辑时的冲突。
-
-
协同功能实现
-
实现评论和讨论功能,允许用户对文档内容进行注释和讨论。
-
实现文档分享和权限设置,允许用户邀请他人协作或查看文档。
-
实现版本控制和历史记录功能,允许用户查看文档的历史版本和变更。
-
-
安全性和权限管理
-
实现用户认证机制,如OAuth、JWT等。
-
实现基于角色的访问控制(RBAC)或属性基础的访问控制(ABAC)。
-
实现数据加密和安全传输。
-
-
测试
-
进行单元测试、集成测试和系统测试,确保功能正确性。
-
进行性能测试,确保系统能够处理高并发编辑和大量用户。
-
进行安全测试,确保系统没有安全漏洞。
-
-
部署和维护
-
部署应用到服务器或云平台。
-
监控系统性能和用户反馈,进行必要的优化和更新。
-
定期备份数据,确保数据安全。
-
-
用户支持和文档
-
提供用户手册和在线帮助文档。
-
设立用户支持渠道,如在线客服、论坛等。
-
离线包怎么做的,现在公司的app提供了那些特殊能力
将应用程序及其依赖的资源预先下载并打包,以便在没有网络连接的环境中安装和使用。
公司app可能会提供以下特殊能力:
- 离线使用:允许用户在没有网络连接的情况下使用app的某些功能。
- 个性化服务:根据用户的行为和偏好提供定制化的内容或服务。
- 增强现实(AR)功能:通过手机摄像头提供增强现实体验。
- 人工智能(AI)集成:使用AI技术提供智能推荐、语音识别、图像识别等功能。
- 安全和隐私保护:提供高级加密和隐私保护措施,确保用户数据安全。
质量保障平台如何做的
质量保障平台的构建和项目中单元测试、端到端测试(E2E测试)的实施是确保软件产品质量的关键步骤。
质量保障平台的构建
- 需求分析:明确平台需要支持的测试类型、集成的工具、报告的格式等。
- 工具选择:选择合适的测试工具和框架,如Selenium、Jest、Cypress等。
- 集成开发:开发或配置自动化脚本,集成持续集成/持续部署(CI/CD)工具,如Jenkins、GitLab CI等。
- 测试数据管理:建立测试数据的生成、管理和清理机制。
- 结果分析与报告:开发结果分析工具,生成测试报告,提供质量趋势分析。
- 监控与报警:设置监控机制,当测试失败或质量下降时,及时通知相关人员。
- 持续改进:根据测试结果和用户反馈,不断优化测试流程和平台功能。
项目中单元测试的实施
单元测试是测试软件中最小可测试单元(通常是函数或方法)的过程。单元测试的目的是确保每个单元按预期工作。实施单元测试通常包括:
- 编写测试用例:为每个单元编写测试用例,覆盖各种输入和边界条件。
- 使用测试框架:使用如JUnit、Mocha、Jest等测试框架来组织和运行测试。
- 断言:使用断言来验证代码的输出是否符合预期。
- 重构与优化:在测试的指导下重构代码,提高代码质量和可测试性。
- 持续集成:将单元测试集成到CI/CD流程中,确保每次代码提交都通过测试。
端到端测试(E2E测试)的重要性
E2E测试的重要性包括:
- 模拟用户与应用程序的交互,验证整个应用程序从开始到结束的流程是否按预期工作。
- 在软件更新后,确保新没有破坏现有功能。
devserver怎么跑起来的
允许开发者在本地环境中模拟生产环境,以便于开发和测试。
以Webpack DevServer为例,它是一个小型的Node.js Express服务器,用于在开发过程中提供静态文件服务,并支持热重载等功能。
emit事件怎么发
emit
事件通常是指在事件驱动的编程模型中,一个对象(如组件、模块等)触发一个事件,并将这个事件传递给其他对象或函数进行处理。
jsonp方案需要服务端怎么配合
//服务端需要接收一个名为callback的参数,这个参数的值是客户端期望用来包裹JSON数据的函数名
myFunction({ "name": "John", "age": 30 });
// 后端返回JSONP格式的数据
res.type('application/javascript');
res.send(`${callback}(${JSON.stringify(data)});`);
- JSONP只支持GET请求。
- JSONP不支持HTTPS,因为
<script>
标签请求不支持HTTPS到HTTP的降级。 - JSONP存在安全风险,因为它允许执行任意的JavaScript代码。因此,服务端应该对返回的数据进行严格的验证和清洗,避免XSS攻击等安全问题。
JSONP是一种老旧的技术,现代的Web开发中更推荐使用CORS(跨源资源共享)来处理跨域请求问题
ajax发送跨域设置什么,axios,fetch
使用 jQuery 发送跨域 AJAX 请求时,需要设置 $.ajaxSetup
({crossDomain: true})
axios默认支持,明确可以withCredentials:true
Fetch 发送跨域请求并携带 cookies,需要设置 credential
谈一下你的职业生涯规划
技术和个人方面:
不断的学习新技术,并把所学应用到新技术上,或者做一些个人项目开发,在github blog 或者其他图文做一些技术分析提升影响力,往全栈方向发展,
团队方面: 主动承接一些协调工作和团队管理能力,多看一些管理相关的书,理解用户需求
如何理解数据驱动视图,有哪些核心要素?
强调视图(即用户界面的展示部分)应该直接由数据模型驱动。
- 数据模型是源头。
- 数据模型的任何变化都应该自动触发视图的更新。
- 数据驱动视图中,视图的渲染通常是声明式的。开发者通过声明视图应该如何根据数据模型来渲染,而不是编写命令式代码来控制渲染过程。
- 组件化:将视图分解为可复用的组件,每个组件负责渲染数据模型的一部分。组件化有助于提高代码的可维护性和可重用性。
- 状态管理:在复杂的应用中,需要一种机制来管理应用的状态。状态管理库(如Redux、Vuex等)可以帮助开发者在不同的组件之间共享和管理状态。
- 数据驱动视图中,数据流通常是单向的。
dns协议了解多少?
分布式网络目录服务,它将易于记忆的域名转换为计算机能够理解的IP地址
工作原理:
- 查询过程:当用户尝试访问一个域名时,用户的设备(如电脑、手机)会向配置的DNS服务器发送一个查询请求。
- 递归查询:如果DNS服务器没有该域名的缓存记录,它会向根域名服务器查询,根域名服务器再指向顶级域名服务器,顶级域名服务器再指向权威域名服务器,直到找到对应的IP地址。
- 缓存:在查询过程中,每个DNS服务器都会将查询结果缓存一段时间,以加快后续的查询速度。
- 响应:权威域名服务器返回域名对应的IP地址给用户设备,用户设备使用这个IP地址进行通信。
dns预解析怎么做?
用于提前解析网页中可能需要的域名,以减少用户访问链接时的DNS解析延迟。。
-
HTML Meta标签: 在HTML文档的
<head>
部分,可以添加一个<meta>
标签来指示浏览器进行DNS预解析。<meta http-equiv="x-dns-prefetch-control" content="on">
这个标签告诉浏览器开启DNS预解析功能。
content="on"
表示开启,content="off"
表示关闭。 -
Link标签: 可以使用
<link>
标签的rel
属性来指定需要预解析的域名。<link rel="dns-prefetch" href="http://example.com">
这个标签告诉浏览器对
http://example.com
进行DNS预解析。你可以为页面中将要使用的外部资源指定多个<link>
标签。 -
HTTP头部: 在服务器端,可以通过设置HTTP响应头来启用DNS预解析。
X-DNS-Prefetch-Control: on
这个响应头指示浏览器开启DNS预解析功能。同样地,
on
表示开启,off
表示关闭。
什么是领域模型?
- 领域模型 是对业务领域的抽象,用于描述业务中的实体、关系和规则。
- 作用:
- 帮助开发人员理解业务需求。
- 提供统一的业务语言。
TS 如何把变量绑定在 window 上?
-
使用
declare
:declare global {
interface Window {
myVar: string;
}
}
window.myVar = 'Hello';
Js执行100万个任务,如何保证浏览器不卡顿?
要保证浏览器在执行大量任务时不卡顿,可以采用以下几种策略:
- 分片执行:将任务分成多个小任务,使用
requestIdleCallback
或setTimeout
分批执行,避免长时间占用主线程。 - Web Workers:将计算密集型任务放到 Web Worker 中执行,避免阻塞主线程。
- 异步编程:使用
Promise
、async/await
等异步编程方式,避免阻塞主线程。
function processTasks(tasks) {
let index = 0;
function run() {
if (index >= tasks.length) return;
requestAnimationFrame(() => {
tasks[index]();
index++;
run();
});
}
run();
}
如何一次性渲染十万条数据还能保证页面不卡顿?
可以使用虚拟列表(Virtual List)技术,只渲染可见区域的数据。
function renderList(data) {
const container = document.getElementById('list');
const visibleCount = Math.ceil(container.clientHeight / 30);
const [start, setStart] = useState(0);
const visibleData = data.slice(start, start + visibleCount);
return (
<div onScroll={(e) => setStart(Math.floor(e.target.scrollTop / 30))}>
{visibleData.map(item => <div key={item.id}>{item.name}</div>)}
</div>
);
}
js事件机制,结合一个复杂事件场景?
JavaScript 事件机制包括事件捕获、目标阶段和事件冒泡。可以通过 addEventListener
来监听事件。
document.getElementById('parent').addEventListener('click', (e) => {
console.log('Parent clicked');
}, true); // 捕获阶段
document.getElementById('child').addEventListener('click', (e) => {
console.log('Child clicked');
}); // 冒泡阶段
一直在window上面挂东西是否有什么风险?
- 命名冲突:在全局作用域中添加变量或函数可能会与现有的全局变量或第三方库中的变量发生命名冲突。这可能导致意外的行为或错误。
- 内存泄漏:如果在
window
对象上挂载的对象是大型对象或包含事件监听器等,而这些对象没有被适当地清理或移除,可能会导致内存泄漏。 - 代码维护困难:全局变量和函数的使用使得代码难以维护和理解,特别是在大型项目中。全局变量的修改可能会影响到代码的其他部分,导致难以追踪的错误。
- 安全性问题:在全局作用域中暴露敏感数据或功能可能会增加安全风险。恶意脚本可以通过全局变量访问或修改这些数据。
- 性能影响:过多的全局变量和函数可能会增加全局对象的大小,从而影响性能。加载和执行时,浏览器需要处理更多的全局数据。
移动端如何实现上拉加载,下啦刷新?
FlatList
是React Native中用于渲染长列表数据的组件,它提供了onEndReached
和onRefresh
属性,可以用来实现上拉加载和下拉刷新
前端水印了解多少?
- 实现方案:
- 使用
canvas
生成水印图片。 - 使用
CSS
的background-image
添加水印。 - 通过
MutationObserver
防止水印被删除。
- 使用
web网页如何禁止别人移除水印
使用Canvas绘制水印:通过Canvas API在网页上绘制水印,这样水印就嵌入到了网页的图像中,用户无法轻易移除
JavaScript动态生成水印:使用JavaScript动态地在页面上生成水印,这样用户就无法通过查看源代码找到水印的HTML或CSS代码。
监听DOM操作:通过监听DOM的变化,可以检测到页面内容是否被修改。如果检测到修改,可以采取措施,比如弹出警告或重新加载页面
使用CSS样式:将水印作为背景图或使用CSS的text-shadow
属性来创建水印。这些方法使得水印难以通过简单的右键菜单移除。
js中如何实现对大对象深度对比
需要递归地检查每个属性是否相等。对于简单类型(如字符串、数字、布尔值等),可以直接使用 ===
进行比较。对于复杂类型(如对象、数组等),则需要递归地比较它们的每个属性或元素。
如何统计长任务时间和执行次数
// 使用PerformanceObserver来监听长任务
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.entryType === 'longtask') {
console.log('长任务执行时间:', entry.duration);
console.log('长任务执行次数:', list.getEntriesByType('longtask').length);
}
});
});
// 配置观察器以监听长任务
observer.observe({ entryTypes: ['longtask'] });
ts项目中,如何使用node_modules里面定义的全局类型包到自己项目src下面使用?
tsconfig.json
文件中,需要确保compilerOptions
部分包含了正确的配置
如果你的项目中使用了typeRoots
配置,确保node_modules/@types
目录
如果你的项目中使用了types
配置,你可以直接指定要包含的类型定义包的名称
如果你使用的是TypeScript 3.8或更高版本,typeRoots
和types
配置是可选的,因为TypeScript默认会包含node_modules/@types
目录下的所有类型定义。
在react项目开发中,是否可以不用react router使用浏览器原生history路由来组织页面路由?
// npm install history
import React from 'react';
import { Router, Route } from 'react-router-dom';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
const App = () => (
<Router history={history}>
<div>
<Route exact path="/" component={HomePage} />
<Route path="/about" component={AboutPage} />
{/* 其他路由配置 */}
</div>
</Router>
);
const navigateToAbout = () => {
history.push('/about');
};
注意事项
- 使用原生
history
API时,你将失去React Router提供的许多高级功能,如动态路由、路由守卫、路由匹配等。 - 你需要手动处理路由状态的更新和组件的重新渲染。
表单教研场景中,如何实现页面视口滚动到报错的位置
原生JavaScript的scrollIntoView()
方法来实现滚动到指定元素的位置
behavior: 'smooth'
,以提供更平滑的滚动体验。
webpack项目中通过script标签引入资源,再项目中如何处理?
html-webpack-plugin
是一个非常流行的Webpack插件,它可以帮助你将资源文件自动注入到HTML模板中。你可以通过配置html-webpack-plugin
来指定需要通过<script>
标签引入的资源
如何检测网页的空闲状态?
1,requestIdleCallback
,
2, 监听 点击、滚动、鼠标、+ setTimeout
列表分页,快速翻页下的竞态问题
可能发生在用户快速连续点击分页按钮时,使用防抖、节流、加载loading并禁用按钮
如何禁止别人调式自己的前端页面代码?
通过在代码中不断执行debugger
语句,可以阻止调试器正常工作。当调试器打开时,debugger
语句会导致程序暂停,从而无法进行断点调试
通过监听事件,可以禁用右键菜单和快捷键
Oauth2.0是什么登录方式?
允许第三方应用(客户端)通过用户代理(通常是Web浏览器)获取对服务器资源的有限访问权限
- 用户代理重定向:用户在第三方应用中点击登录按钮,第三方应用将用户代理(浏览器)重定向到授权服务器。
- 用户认证:用户在授权服务器上进行认证,这通常涉及输入用户名和密码。
- 授权:用户在认证后,授权服务器会询问用户是否同意第三方应用访问其信息。用户同意后,授权服务器会生成一个授权码(Authorization Code)。
- 获取访问令牌:第三方应用使用授权码向授权服务器请求访问令牌(Access Token)。
- 访问资源:第三方应用使用访问令牌向资源服务器请求访问用户的数据。
前端如何设置请求超时时间?
XMLHttpRequest
xhr.timeout = 5000;
Fetch API本身不直接支持设置超时,但可以通过结合Promise.race
和AbortController
来实现
axios timeout
meta标签有哪些?
视口设置
<meta name="viewport" content="width=device-width, initial-scale=1.0">
描述页面内容
<meta name="description" content="页面的简短描述">
关键词
指定文档的刷新 ,这行代码指定页面在30秒后自动刷新。
<meta http-equiv="refresh" content="30">
指定文档的缓存控制
<meta http-equiv="cache-control" content="no-cache">
指定文档的编码方式
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
XHR具体底层原理,要求手写ajax
function ajax(url, method, callback) {
// 创建XHR对象
var xhr = new XMLHttpRequest();
// 配置请求
xhr.open(method, url, true);
// 设置请求完成后的回调函数
xhr.onreadystatechange = function() {
// 当请求完成时
if (xhr.readyState === XMLHttpRequest.DONE) {
// 检查HTTP状态码
if (xhr.status === 200) {
// 请求成功,调用回调函数
callback(xhr.responseText);
} else {
// 请求失败,调用回调函数
callback('Error: ' + xhr.status);
}
}
};
// 发送请求
xhr.send();
}
// 使用手写AJAX发送GET请求
ajax('https://api.example.com/data', 'GET', function(response) {
console.log(response);
});
项目中遇到的一些问题,怎么解决的
确定问题,查看错误信息、用户反馈、代码
使用调试工具、代码审查分析问题
根据问题的原因,制定一个或多个可能的解决方案
选一个较优的方案进行实施
之后测试和验证,并记录这次问题的详细过程和解决方案,方便后续回顾和积累经验,防止类似的问题在次发生,
面对产品不断迭代,以及需求的变动该怎么应对,具体技术方案实现?
采用敏捷开发方法,可以快速响应需求变化
采用微服务架构可以将产品拆分为多个独立的服务,每个服务负责一部分功能
将产品设计为模块化和组件化的结构,每个模块或组件负责一个独立的功能。
使用版本控制系统(如Git)来管理代码变更
编写清晰的文档,并通过代码注释、技术博客、会议等方式进行知识共享
定期进行代码重构,以提高代码质量和可维护性
收集和分析用户反馈和产品使用数据
识别和管理技术债务,确保技术基础的健康
源码解析器是什么
用于分析和理解源代码的工具或程序
由两部分组成:词法分析器(Lexer)和语法分析器(Parser)
语法分析,语义分析,代码遍历,代码转换,代码检查,文档生成
用户操作记录回溯工具是为了解决什么问题?
用户操作记录回溯工具主要用于解决以下问题:
-
审计和合规性:在金融、医疗、法律等行业,需要记录用户的操作以满足合规性要求。这些记录可以用于审计,确保用户操作符合规定和标准。
-
问题诊断和调试:当系统出现错误或异常时,通过回溯用户操作记录,可以快速定位问题发生的原因,帮助开发者或技术支持人员进行问题诊断和调试。
-
安全事件调查:在安全事件发生时,如数据泄露、未授权访问等,用户操作记录可以作为关键证据,帮助调查事件的起因和过程。
-
用户体验优化:通过分析用户操作记录,可以了解用户在使用产品或服务时的行为模式,从而发现潜在的用户体验问题,并据此进行优化。
-
业务流程分析:在业务流程中,用户操作记录可以用来分析流程效率,识别流程瓶颈,优化业务流程。
-
数据恢复:在数据丢失或损坏的情况下,用户操作记录可以作为数据恢复的依据,帮助恢复到特定的操作状态。
-
用户行为分析:通过分析用户操作记录,可以了解用户的使用习惯和偏好,为产品设计和市场营销提供数据支持。
-
防止欺诈行为:在电子商务、在线支付等领域,用户操作记录可以用于检测和预防欺诈行为。
用户操作记录回溯工具通常包括以下几个关键功能:
- 记录捕获:能够捕获用户在系统中的所有操作,包括点击、输入、页面跳转等。
- 数据存储:将捕获的操作记录存储在数据库或日志文件中,确保数据的完整性和可追溯性。
- 查询和检索:提供强大的查询和检索功能,方便用户根据时间、用户、操作类型等条件快速找到相关记录。
- 回放和分析:能够回放用户的操作过程,帮助分析用户行为和系统响应。
- 安全和权限管理:确保只有授权的用户才能访问和操作用户操作记录。
对业务的理解,已经一些想法
首先需要看下这个事情是一个简单的事情还是一个复杂的事情,如果是一个简单的事情的话,其实比较好的评估这个事情的工作量,对于复杂的问题来说,我理解首先需要做的事情是拆解这个复杂的事情,将其拆解成几部分清晰的部分,然后对于每一个部分做评估,这样评估起来就比较容易了。
了解消息中间件吗?
消息中间件(Message Middleware)是一种在分布式系统中用于实现不同系统组件之间异步通信的软件系统。它作为消息的代理,负责在生产者(发送消息的系统或服务)和消费者(接收消息的系统或服务)之间传递消息。消息中间件通常用于解耦系统组件、提高系统的可扩展性和可靠性。
消息中间件的主要特点包括:
-
异步通信:消息中间件支持异步通信模式,生产者发送消息后不需要等待消费者处理完成即可继续执行其他任务。
-
解耦:通过消息中间件,生产者和消费者之间不需要直接通信,从而实现了解耦,使得系统更加灵活和可扩展。
-
可靠性:消息中间件通常提供消息持久化、事务支持、消息确认等机制,确保消息的可靠传递。
-
负载均衡:消息中间件可以实现消息的负载均衡,将消息均匀地分配给多个消费者处理,提高系统的处理能力。
-
消息队列:消息中间件通常包含消息队列,用于存储待处理的消息,支持消息的排队、优先级处理等。
常见的消息中间件产品包括:
-
Apache Kafka:一个分布式流处理平台,广泛用于构建实时数据管道和流应用程序。
-
RabbitMQ:一个开源的消息代理软件,支持多种消息协议,易于使用和扩展。
-
ActiveMQ:一个开源的消息代理和集成服务器,支持多种消息协议和传输方式。
-
Redis:虽然主要是一个内存数据结构存储系统,但其发布/订阅功能也可以用作消息中间件。
消息中间件的应用场景:
-
异步处理:在需要异步处理的场景中,如订单处理、邮件发送等。
-
系统解耦:在需要解耦的系统组件之间,如微服务架构中的服务间通信。
-
流量削峰:在流量波动较大的场景中,如电商平台的促销活动。
-
日志收集:在需要集中收集和处理日志的场景中。
-
实时数据处理:在需要实时处理数据的场景中,如实时分析、监控告警等。
10000个数选前10大的数字
排序区10个,使用10个队列
为什么不能完全使用对称加密
密钥交换问题
对称加密的一个主要问题是密钥交换。如果使用对称加密,那么通信双方必须共享同一个密钥。在互联网上,安全地共享密钥是一个挑战,因为密钥在传输过程中可能会被截获。如果密钥被第三方截获,那么所有的通信内容都将被破解。
初始信任问题
在对称加密中,通信双方需要在开始通信之前就建立信任关系,以确保密钥的安全交换。这在互联网上很难实现,因为用户可能从未见过对方,也没有其他方式来验证对方的身份。
3. 密钥管理问题
对称加密的另一个问题是密钥管理。在大规模的网络通信中,每个用户对都需要一个唯一的密钥。随着用户数量的增加,密钥的数量也会成倍增加,这使得密钥的管理变得非常复杂和困难。
4. 安全性问题
对称加密算法通常比非对称加密算法更快,但它们在安全性方面通常不如非对称加密算法。非对称加密算法(如RSA、ECC等)使用一对密钥(公钥和私钥),其中公钥可以公开分享,而私钥保持私有。这种机制使得密钥交换更加安全,因为即使公钥被截获,没有私钥也无法解密通信内容。
webview加载一般耗时多久?
- 快速加载:在良好的网络条件下,页面加载可能在几百毫秒到一两秒内完成。
- 中等加载:在一般网络条件下,页面加载可能需要几秒到十几秒。
- 慢速加载:在较差的网络条件下或资源较多的页面,加载时间可能超过十几秒。
如何解决页面请求接口大规模并发问题?
- 解决方案:
- 使用
Promise.all
并发请求。 - 设置请求队列,限制并发数。
- 使用缓存(如 Redis)减少重复请求。
- 使用
站点一键换肤的实现方式有哪些?
- 实现方案:
- 使用 CSS 变量动态切换主题。
- 通过
class
或data-*
属性切换样式表。 - 使用
styled-components
或emotion
动态生成样式。
Web 应用中如何对静态资源加载失败的场景降级处理?
- 解决方案:
- 使用
onerror
事件加载备用资源。 - 通过
Service Worker
缓存资源。 - 使用
CDN
提供高可用性。
- 使用
3. 前端如何用canvas来做电影院选票功能?
使用 Canvas 实现电影院选票功能,可以通过绘制座位图、处理点击事件来实现。
const canvas = document.getElementById('seat-map');
const ctx = canvas.getContext('2d');
const seats = [
{ x: 50, y: 50, width: 30, height: 30, status: 'available' },
{ x: 100, y: 50, width: 30, height: 30, status: 'occupied' },
];
function drawSeats() {
seats.forEach(seat => {
ctx.fillStyle = seat.status === 'available' ? 'green' : 'red';
ctx.fillRect(seat.x, seat.y, seat.width, seat.height);
});
}
canvas.addEventListener('click', (event) => {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
seats.forEach(seat => {
if (x >= seat.x && x <= seat.x + seat.width && y >= seat.y && y <= seat.y + seat.height) {
if (seat.status === 'available') {
seat.status = 'selected';
drawSeats();
}
}
});
});
drawSeats();
前端应用如何做灰度发布?
- 实现方案:
- 通过 Nginx 配置,按用户 IP 或 Cookie 分流。
- 使用 Feature Flag 控制功能开关。
- 通过 CDN 配置,按区域或用户比例分发不同版本。
一般是怎么做代码重构的?
- 步骤:
- 编写测试用例,确保重构前后功能一致。
- 使用工具(如 ESLint、Prettier)规范代码风格。
- 提取重复代码为函数或组件。
- 优化数据结构,减少嵌套层级。
- 使用设计模式(如工厂模式、策略模式)优化代码结构。
如何减少项目中 if-else?
-
策略模式:将条件分支抽象为策略对象。
-
多态:利用面向对象的多态特性,将不同条件下的行为封装到不同的类中。
-
表驱动法:使用对象或 Map 来映射条件与对应的处理函数。
-
提前返回:通过提前返回来减少嵌套层级。
-
示例:
// 优化前
if (type === 'A') {
handleA();
} else if (type === 'B') {
handleB();
} else {
handleDefault();
}
// 优化后
const handlers = {
A: handleA,
B: handleB,
default: handleDefault,
};
(handlers[type] || handlers.default)();
检测内存的例子?
-
内存泄漏检测:可以通过浏览器的开发者工具(如 Chrome DevTools)检测内存泄漏。
-
示例代码:
// 模拟内存泄漏
let leakedArray = [];
setInterval(() => {
for (let i = 0; i < 10000; i++) {
leakedArray.push(new Array(1000).fill("leak"));
}
console.log("Memory usage:", window.performance.memory);
}, 1000); -
检测步骤:
- 打开 Chrome DevTools,切换到 Memory 选项卡。
- 使用 Heap Snapshot 或 Allocation Instrumentation on Timeline 工具记录内存分配情况。
- 分析内存增长情况,找到未释放的对象。
如何实现预览 PDF 文件
-
使用
<iframe>
:<iframe src="/path/to/file.pdf" width="100%" height="500px"></iframe>
-
使用 PDF.js:
-
PDF.js 是 Mozilla 开源的 PDF 渲染库,可以在浏览器中直接渲染 PDF 文件。
-
示例:
const pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.getDocument('/path/to/file.pdf').promise.then(pdf => {
pdf.getPage(1).then(page => {
const canvas = document.getElementById('pdf-canvas');
const context = canvas.getContext('2d');
const viewport = page.getViewport({ scale: 1.5 });
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({ canvasContext: context, viewport });
});
});
-
Docker 和虚拟机的区别
- Docker 是轻量级的容器化技术,使用共享内核,启动速度快,资源占用小。
- 虚拟机 提供完整的虚拟硬件,每个 VM 都有独立的操作系统,启动慢,资源占用大。
Docker 通常用于开发和部署微服务,CI/CD 流程中可以快速构建、测试和部署。
兼容性的问题一般怎么看
兼容性问题通常可以通过以下方式解决:
- 使用工具如 "Can I Use" 检查浏览器对特性的支持情况。
- 在实际设备或模拟器上进行测试。
APP 和 H5 具体怎么调试
调试 APP 和 H5 时,可以使用:
- Chrome DevTools:用于调试 Web 应用。
- Safari Web Inspector:用于调试 iOS 应用。
- 代理工具:如 Charles 或 Fiddler,进行网络请求抓包分析。
跨域情况下如何获取到别的页面 localStorage 里的数据
跨域情况下无法直接访问其他域的 localStorage。可以考虑使用 postMessage
API,在安全的前提下进行数据传递。
i18n 原理
文本抽取
// en.json
{
"greeting": "Hello",
"farewell": "Goodbye"
}
// fr.json
{
"greeting": "Bonjour",
"farewell": "Au revoir"
}
语言文件
每种支持的语言会有一个对应的语言文件,文件中包含了所有需要翻译的文本的键值对。通过这种方式,应用可以根据用户的语言偏好加载相应的文件。
用户语言检测
- 从浏览器的
navigator.language
获取用户的语言设置。 - 提供用户选择语言的选项,并将其保存在本地存储或 Cookie 中。
动态文本渲染
根据用户的语言偏好,应用在渲染时会加载相应的语言文件,并将文本替换为对应的翻译。例如,在 React 中,可以使用上下文或库(如 react-i18next
)来实现动态文本渲染。
import { useTranslation } from 'react-i18next';
const Greeting = () => {
const { t } = useTranslation();
return <h1>{t('greeting')}</h1>;
};
格式化和地区设置
除了文本翻译,i18n 还需要考虑日期、时间、数字、货币等的格式化。这些格式通常依赖于地区设置。例如:
- 使用
Intl.DateTimeFormat
来格式化日期。 - 使用
Intl.NumberFormat
来格式化数字。
右到左语言支持
对于某些语言(如阿拉伯语和希伯来语),需要支持从右到左的布局。这通常涉及到 CSS 的调整,确保文本和界面元素的方向正确。
观察者模式 vs 发布-订阅模式
特性 | 观察者模式 | 发布-订阅模式 |
---|---|---|
通信方式 | 直接通信(主题直接通知观察者) | 间接通信(通过事件中心) |
耦合度 | 强耦合(主题和观察者相互依赖) | 松耦合(发布者和订阅者解耦) |
角色 | 主题(Subject)和观察者(Observer) | 发布者(Publisher)、订阅者(Subscriber)、事件中心(Event Bus) |
实现复杂度 | 简单 | 较复杂(需要实现事件中心) |
适用场景 | 对象间直接依赖的场景 | 需要解耦的场景,如事件驱动架构 |
同步/异步 | 通常是同步 | 可以是同步或异步 |