不是做有网站都叫jwth/百度指数分析官网
1.你的项目在哪些浏览器上测试过?如何解决浏览器的兼容问题?
1. 使用工具检测兼容性问题:比如Can I Use网站来检查CSS、JS特性的支持情况。还有像Autoprefixer这样的工具自动添加CSS前缀,避免手动写-webkit-、-moz-之类的。
2. 使用Babel转译ES6+代码为ES5,这样旧浏览器也能运行。同时可能需要引入core-js这样的polyfill库来补充缺失的API,比如Promise、fetch等。
3. 在CSS方面,使用Reset CSS或Normalize.css来统一不同浏览器的默认样式差异。可能还需要处理Flexbox或Grid布局在旧版本浏览器中的兼容问题,比如IE10部分支持Flex,可能需要写一些fallback布局。
4. 针对特定浏览器的Hack,比如条件注释针对IE,或者使用特定的CSS前缀。不过现在可能更倾向于特性检测,而不是浏览器检测,用Modernizr之类的库来判断是否支持某特性,再决定加载相应的polyfill。
5. 测试阶段使用工具,比如BrowserStack进行跨浏览器测试,或者在本地用不同浏览器和版本进行测试。可能还需要用Lint工具如ESLint、Stylelint来避免使用不兼容的语法。
回答示例
“在之前的项目中,我会首先通过用户数据分析确定需要支持的浏览器范围,例如支持Chrome、Firefox、Edge的最新两个版本,开发阶段,我会使用Autoprefixer自动处理CSS前缀,通过Babel转译ES6+代码并注入必要的Polyfill。同时采用渐进增强策略,确保基础功能在所有浏览器可用。测试时,除了本地多浏览器调试,还会用BrowserStack覆盖更多环境。例如,在xx项目中需要兼容IE11,我们针对Flex布局问题添加了-ms前缀,并为Promise等API引入了core-js polyfill,最终实现了平稳运行。”
2.说一下项目中的token如何实现自动刷新(无感刷新)的
无感刷新就是在 Access Token 过期时,不需要用户看到任何界面提示,通过后台自动刷新 Access Token。
- 常见的做法是使用 短期有效的 Access Token 和 长期有效的 Refresh Token 配合。Access Token 一般用于请求 API,而 Refresh Token 用于获取新的 Access Token。
- 前端可以使用拦截器(如 Axios 的请求拦截器)来自动处理请求。在每次请求时,首先检查 Access Token 是否有效。如果 Access Token 过期,前端应该自动发送一个请求到服务器,通过 Refresh Token 获取新的 Access Token。
- 如果刷新失败(如 Refresh Token 也过期),则需要用户重新登录。
3.研发流程
产品经理---提需求文档(PRD)---开需求评审会---技术文档(前后端一起)---技术评审(研发一起)---开发---feat分支---联调---改bug---过case---提测---跟测(提bug改)---提mr(合并主分支)---审核代码---上线
4.职业规划是怎么样的?
短期打算对公司使用的框架进行深耕,并且向全栈方向发展,学习后端开发和mysql,持续的对技术博客总结和运营。
长期打算往全栈工程师方向发展。
5.项目中封装了什么公共方法?如何实现?
公共方法
1. 请求层封装(Axios + uni.request)
实现目标:统一处理请求配置、拦截器、错误码,响应时间及跨域问题。
2. 工具类函数封装(纯函数)
日期格式化:
ISO 8601 标准的日期时间用日期工具库转化
export const formatDate = (timestamp, format = 'YYYY-MM-DD HH:mm') => {return dayjs(timestamp).format(format);
};
本地存储安全读写:
它实现了两个方法:get
和 set
,分别用于从 localStorage
中读取和存储数据,并且在存储时会将数据序列化为 JSON 字符串,在读取时会将 JSON 字符串反序列化为 JavaScript 对象。
export const safeStorage = {get(key) {try {return JSON.parse(localStorage.getItem(key));} catch (e) {return null;}},set(key, value) {localStorage.setItem(key, JSON.stringify(value));}
};
公共组件
1. 智能分页器组件
应用场景:题库列表、用户管理、订单记录等分页需求。
技术实现:
-
功能特性:
-
支持自定义每页条数(10/20/50)
-
集成页码跳转输入框
-
显示总条数和当前页范围
-
适配不同后端分页参数命名(如
page
vscurrent
)
-
6.如何将 Token 存储在 Pinia 中实现持久化管理,并配置在请求和响应的拦截器中。
在 Pinia 中存储 Token
- 使用 Pinia 管理 Token,并将其存储在
localStorage
或sessionStorage
中以保持持久化。 -
// stores/auth.js import { defineStore } from 'pinia';export const useAuthStore = defineStore('auth', {state: () => ({token: localStorage.getItem('token') || '', // 从 localStorage 获取 Token}),actions: {// 登录成功后设置 TokensetToken(token) {this.token = token;localStorage.setItem('token', token); // 保存 Token 到 localStorage},// 登出时清除 TokenclearToken() {this.token = '';localStorage.removeItem('token'); // 从 localStorage 删除 Token},},persist: true, // Pinia 持久化插件,这样状态会在刷新后保存 });
- 配置 Axios 请求拦截器,在每个请求中自动添加 Authorization Header。
- 配置 Axios 响应拦截器,处理 Token 过期或错误,并在需要时清除 Token。
- 在登录和登出过程中调用 Pinia store 的相应方法来管理 Token。
安装 Pinia 持久化插件(可选)
如果您希望 Pinia 状态持久化,可以使用 Pinia 的持久化插件(比如 pinia-plugin-persistedstate
)来保证状态在页面刷新后保持不变。
配置 Axios 请求和响应拦截器
// 如果 Token 存在,将其添加到请求头if (token) {config.headers['Authorization'] = `Bearer ${token}`;}
7.分别设置了哪些路由导航守卫?在哪里设置的,实现了什么功能?
全局前置守卫
- 设置位置:我在 Vue3 项目的入口文件(通常是
main.js
或router.js
)中进行了全局前置守卫的配置。 - 功能:该守卫的主要作用是在每次路由跳转之前执行一些操作。我们主要利用这个守卫来处理用户的认证状态和权限校验。
- 验证 Token 是否有效:每次跳转前,我会检查存储在 Pinia 中的 Token 是否存在,并且是否有效。如果没有有效的 Token,我会通过
router.push
跳转到登录页面。 - 跳转到登录页面:如果用户未登录,或者 Token 无效,系统会自动跳转到登录页,确保未授权的用户无法访问受保护的页面。
- 自动跳转:一旦用户成功登录,并且成功获得新的 Token,我会通过守卫来控制跳转到之前请求的页面,提升用户体验。(可以利用 Vue Router 中的导航守卫,结合 Vuex 或 localStorage 来存储用户登录前的请求地址,从而在登录成功后重定向到用户原本想访问的页面。)
- 验证 Token 是否有效:每次跳转前,我会检查存储在 Pinia 中的 Token 是否存在,并且是否有效。如果没有有效的 Token,我会通过
8.如何实现用 Element-UI 图片上传组件,结合 vue-cropper 完成头像上传功能
安装了所需的依赖,包括 Element-UI 和 vue-cropper。
引入 Element-UI 和 vue-cropper,使用并配置属性:比如是否可以缩放旋转等等。
当用户选择文件后,FileReader 读取文件并将其转换为 Base64 格式。
将读取到的 Base64 数据存储,供裁剪组件使用。
将 showCropper 设置为 true,显示裁剪组件。
阻止 Element-UI 的默认上传行为,因为我们将在裁剪后手动上传图片。
调用vue-cropper中的各种方法实现旋转,缩放等功能
当用户完成裁剪操作后,VueCropper 会触发 crop-success 事件,并返回裁剪后的图片 Base64 数据。
将裁剪后的图片作为 Blob 数据添加到 FormData 中发送上传到阿里云OSS
9.支持微信小程序刘海屏适配功能
1.使用 safe-area
适配刘海屏
微信小程序提供了 safe-area-inset-top
、safe-area-inset-left
、safe-area-inset-right
、safe-area-inset-bottom
等 CSS 环境变量,用来处理设备的刘海区域,确保内容不被遮挡。
2. 使用 getSystemInfoSync()
获取设备信息
可以通过 wx.getSystemInfoSync()
API 获取设备的屏幕信息、刘海区的情况等。在获取设备信息后,你可以判断设备是否为刘海屏,并动态调整布局。
3. 适配状态栏和底部安全区域
/* 避免顶部状态栏遮挡 */
.status-bar {padding-top: env(safe-area-inset-top);height: env(safe-area-inset-top);background-color: #000;
}/* 底部安全区域适配 */
.footer {padding-bottom: env(safe-area-inset-bottom);background-color: #000;color: white;text-align: center;height: 50px;
}
10.提交按钮支付功能完成微信支付如何实现
-
后端生成预支付订单
首先,后端系统会调用微信支付的统一下单接口,生成一个预支付订单。这个过程完成后,后端会拿到一个关键的prepay_id
,后端拿到prepay_id
后,会用它生成一个package
参数。package
的格式通常是prepay_id=xxxx
,其中xxxx
就是prepay_id
的值。后端会把生成好的package
(以及其他必要的参数,如timeStamp
、nonceStr
、paySign
等)返回给前端。 -
调用
wx.requestPayment
:前端拿到这些参数后,将它们一起传入wx.requestPayment
方法,发起支付请求。 -
支付回调
支付成功或失败后,微信支付会回调我们服务器的接口。我们需要在服务器端处理这些回调,比如记录支付结果等。
11.wangEditor实现学生笔记功能,遇到的问题
第一步:先把编辑器搭起来
"首先我在Vue项目里集成了wangEditor这个富文本编辑器,就像搭积木一样先把它装到页面上。配置了基本的文本编辑功能,比如加粗、标题、列表这些学生记笔记常用的格式选项。"
第二步:搞定图片上传
"然后我实现了图片上传功能,这里有几个关键点:
-
对接了后端的图片上传接口
-
加了图片大小限制(最大5MB),太大的图片不让传
-
用Canvas做了图片压缩,这样上传更快更省流量
-
加了上传进度条,让学生知道图片传到哪里了"
第三步:代码高亮支持
"因为学生经常要记代码笔记,我特别加了代码块高亮功能:
-
集成了highlight.js这个库
-
支持了10多种编程语言
-
选了护眼的暗色主题
-
在工具栏加了专门的代码块按钮"
第四步:导出Word文档
"这个是最花功夫的部分,我用了docx.js这个库在前端直接生成Word文件:
-
先把编辑器里的内容转成Word能识别的格式
-
处理图片转换,把网络图片下载下来转成Base64
-
保持格式一致性,比如代码块在Word里也要有背景色
-
最后做成一个按钮,点一下就能下载Word文件"
挑战一:大文档导出卡顿
-
问题:50页以上的笔记导出时浏览器冻结
-
优化手段:
-
分块处理:将内容拆分为多个
Section
,分段生成 -
进度提示:添加进度条组件,显示“正在生成第X页...”
-
Web Worker:将格式转换逻辑放入后台线程
-
使用Canvas实现图片压缩的详细实现方案
这样可以显著减少上传流量消耗和服务器存储压力。以下是具体实现方法:
-
将图片文件加载到
<canvas>
元素中 -
通过调整canvas绘制尺寸和质量参数实现压缩
-
将canvas内容导出为压缩后的图片文件
/*** 使用Canvas压缩图片* @param {File} file - 原始图片文件* @param {Object} options - 压缩选项* @param {number} [options.maxWidth=1920] - 最大宽度* @param {number} [options.maxHeight=1080] - 最大高度 * @param {number} [options.quality=0.8] - 压缩质量(0-1)* @param {string} [options.mimeType=image/jpeg] - 输出格式* @returns {Promise<Blob>} - 返回压缩后的图片Blob对象*/
function compressImage(file, options = {}) {return new Promise((resolve, reject) => {const { maxWidth = 1920, maxHeight = 1080,quality = 0.8,mimeType = 'image/jpeg' } = options;// 创建图片对象const img = new Image();img.src = URL.createObjectURL(file);img.onload = () => {// 计算缩放比例let width = img.width;let height = img.height;if (width > maxWidth || height > maxHeight) {const ratio = Math.min(maxWidth / width,maxHeight / height);width = Math.floor(width * ratio);height = Math.floor(height * ratio);}// 创建Canvasconst canvas = document.createElement('canvas');canvas.width = width;canvas.height = height;// 绘制图片const ctx = canvas.getContext('2d');ctx.drawImage(img, 0, 0, width, height);// 转换为Blobcanvas.toBlob((blob) => {if (!blob) {reject(new Error('Canvas转Blob失败'));return;}// 压缩后文件大小比原文件大时返回原文件if (blob.size > file.size) {resolve(file);} else {resolve(blob);}},mimeType,quality);// 释放内存URL.revokeObjectURL(img.src);};img.onerror = () => {reject(new Error('图片加载失败'));URL.revokeObjectURL(img.src);};});
}
12. Vue I18n 实现多语言切换功能
Vue3后台管理系统的国际化,多语言转换!(中文英文繁体)-CSDN博客
13.程序的跨平台兼容性适配
1. 使用统一的布局单位
-
rem 单位:在项目中统一使用
rem
单位进行布局,以确保不同屏幕尺寸下的适配性。通过动态设置根元素的字体大小(html
元素的font-size
),可以根据屏幕宽度动态调整布局大小。
2. 条件编译与媒体查询
-
条件编译:利用 Uniapp 的条件编译功能,针对不同平台编写特定的样式代码。例如,对于 iOS 和 Android 的样式差异,可以使用
#ifdef H5
、#ifdef APP-PLUS
等指令。 -
媒体查询:使用 CSS 媒体查询,根据屏幕宽度、高度、分辨率等条件设置不同的样式。这可以帮助解决不同设备之间的样式差异
3. 多端调试与测试
-
多平台调试工具:利用 Uniapp 提供的多端调试工具,如内置浏览器调试、小程序开发者工具联调等,对应用进行充分的测试。确保在 iOS 和 Android 平台上都能正常运行。
14.MiniIO对象存储服务,通过CDN加速访问
1. 配置MinIO对象存储服务
-
安装并启动MinIO服务:在服务器上安装MinIO,并启动服务。MinIO是一个高性能的对象存储服务,支持S3协议,可以方便地存储和管理静态资源。
-
创建存储桶:通过MinIO客户端或管理界面创建一个存储桶(Bucket),用于存放船舶3D模型、大尺寸产品图片等静态资源。
-
上传静态资源:使用MinIO客户端的上传命令或通过MinIO的API将静态资源上传到创建的存储桶中。例如,可以使用以下Java代码上传文件:
MinioClient minioClient = MinioClient.builder().endpoint("http://your-minio-server:9000/").credentials("your-access-key", "your-secret-key").build();minioClient.uploadObject(UploadObjectArgs.builder().bucket("your-bucket-name").object("your-object-name").filename("path/to/your/file").build());
2. 配置CDN加速
-
选择CDN服务提供商:选择一个可靠的CDN服务提供商,如阿里云CDN、腾讯云CDN等。
-
配置CDN源站:将MinIO对象存储服务的地址配置为CDN的源站。这样,当用户请求静态资源时,CDN会从MinIO获取资源并缓存到CDN节点上。
-
设置缓存规则:根据需要设置CDN的缓存规则,例如缓存时间、缓存路径等,以优化资源的加载速度。
3. 在项目中引用CDN资源
-
修改项目配置:在项目的配置文件中,将静态资源的路径修改为CDN的URL。例如,在HTML模板中引用CDN资源:
HTML复制
<img src="https://cdn.example.com/path/to/your/image.jpg" alt="Product Image"> <script src="https://cdn.example.com/path/to/your/3d-model.js"></script>
预览
-
使用Webpack的externals配置:如果项目使用Webpack打包,可以在Webpack配置中使用externals选项,将静态资源设置为外部依赖,从而避免将它们打包到项目中。例如:
JavaScript复制
module.exports = {externals: {'path/to/your/image.jpg': 'https://cdn.example.com/path/to/your/image.jpg','path/to/your/3d-model.js': 'https://cdn.example.com/path/to/your/3d-model.js'} };
4. 优化项目打包
-
按需加载:对于项目中的其他资源,如JavaScript和CSS文件,可以使用按需加载的方式,减少初始加载的体积。例如,使用Webpack的动态导入功能:
JavaScript复制
const MyComponent = () => import('@/components/MyComponent.vue');
-
代码压缩:使用Webpack的代码压缩插件,如TerserWebpackPlugin,对JavaScript代码进行压缩:
JavaScript复制
const TerserPlugin = require('terser-webpack-plugin'); module.exports = {optimization: {minimize: true,minimizer: [new TerserPlugin()]} };
-
图片优化:使用图片压缩工具,如ImageOptim、TinyPNG等,对图片进行压缩,以减少图片文件的体积。
15.Three.js集成世界地图3D模型
1. 搭建基础场景
-
首先,我会使用 Three.js 创建一个 3D 场景,加载一个世界地图的 3D 模型。这个模型可以是一个地球仪,或者是一个更复杂的地形模型,具体取决于我们的需求。
-
通过 Three.js 的
Scene
、Camera
和Renderer
来搭建基本的 3D 环境。我会设置一个合适的相机位置,让用户一开始就能看到整个地球。
2. 加载世界地图模型
-
使用 Three.js 的
GLTFLoader
或OBJLoader
来加载世界地图的 3D 模型。如果模型比较大,我会优化加载过程,比如使用ProgressiveLoader
来显示加载进度,提升用户体验。 -
加载完成后,将模型添加到场景中,并调整其位置和大小,确保它在视图中居中显示。
3. 实现航线动画
-
对于船舶的航行路径,我会使用 Three.js 的
Line
或Curve
来绘制航线。根据船舶的实际航行数据,计算出航线的起点和终点坐标,然后生成一条平滑的曲线。 -
使用
Tween.js
或 Three.js 自带的动画系统,让船舶沿着这条航线移动。我会设置一个时间间隔,比如每秒移动一定的距离,模拟船舶的航行过程。 -
为了更直观地展示,我会在船舶模型上添加一些动画效果,比如闪烁的灯光或者尾迹效果,让航线更加生动。
4. 添加交互事件
-
使用 Three.js 的
Raycaster
来实现鼠标交互。当用户点击地球上的某个位置时,我会检测鼠标点击的位置是否与船舶或港口模型相交。 -
如果用户点击了船舶,我会弹出一个信息面板,显示船舶的详细信息,比如名称、当前位置、目的地等。
-
如果用户点击了港口,同样会弹出一个面板,展示港口的信息,比如名称、合作项目、货物吞吐量等。
-
我还会添加一些全局的交互事件,比如通过键盘快捷键或鼠标滚轮来控制场景的缩放,通过鼠标拖动来旋转地球,让用户可以自由地查看不同的区域。
5. 数据面板联动
-
在页面上设置一个数据面板,用于展示船舶和港口的详细信息。当用户点击某个船舶或港口时,数据面板会自动更新内容。
-
我会使用 Vue.js 或 React 来管理数据面板的状态,确保数据的实时更新。当用户切换不同的船舶或港口时,面板会通过绑定的数据自动刷新。
-
数据面板还会支持一些交互操作,比如用户可以点击面板上的按钮来查看船舶的历史航行记录,或者港口的合作详情。
6. 优化性能和用户体验
-
由于 3D 场景可能会比较复杂,我会使用一些性能优化技巧,比如使用
LOD
(Level of Detail)来根据相机距离动态切换模型的细节级别,减少渲染压力。 -
我还会使用
WebGLRenderer
的一些优化选项,比如开启antialias
(抗锯齿)和preserveDrawingBuffer
,来提升画面质量。 -
最后,我会对整个应用进行测试,确保在不同设备和浏览器上都能流畅运行,提供良好的用户体验。
16.PDF.js实现泵类产品技术文档的在线预览
1. 集成 PDF.js
-
首先,我会从 PDF.js 官方网站 下载 PDF.js 的最新版本,并将解压后的文件放在项目的
public
目录下。 -
接着,我会在页面中引入 PDF.js 的
viewer.html
,并通过 URL 参数传递 PDF 文件路径。例如:HTML复制
<iframe id="iframe" ref="pdfFile" :src="'pdf/web/viewer.html?file=' + encodeURIComponent(this.pathUrl)" width="100%" height="750px" border="0"> </iframe>
预览
这样,PDF 文件就可以在页面中显示了。
2. 实现页面缩放和跳转功能
-
对于页面缩放,PDF.js 本身支持通过工具栏按钮进行缩放操作。我还会在页面上添加自定义的缩放按钮,通过调用 PDF.js 的 API 来实现缩放功能。
-
页面跳转功能可以通过修改 URL 的
#page
参数来实现。例如:JavaScript复制
const toPage = (page) => {this.$refs.pdfFile.contentWindow.location.hash = `#page=${page}`; };
这样,用户就可以通过输入页码或点击按钮跳转到指定页面。
3. 结合 Ant Design Modal 组件优化阅读体验
-
我会使用 Ant Design 的
Modal
组件来包裹 PDF 预览区域。这样,用户可以在一个弹出窗口中查看文档,而不会干扰页面的其他内容。 -
在
Modal
组件中,我会添加一些自定义的工具栏按钮,比如全屏按钮、关闭按钮等。例如:HTML复制
<a-modal:visible="visible":footer="null"@cancel="handleCancel":body-style="{ padding: '0' }" ><iframeid="iframe"ref="pdfFile":src="'pdf/web/viewer.html?file=' + encodeURIComponent(this.pathUrl)"width="100%"height="100%"border="0"></iframe> </a-modal>
预览
这样,用户可以在一个整洁的环境中查看文档。
4. 支持下载功能
-
在工具栏中添加一个下载按钮,用户点击后会触发 PDF 文件的下载。这可以通过设置一个指向 PDF 文件的
<a>
标签并模拟点击来实现:JavaScript复制
const downloadFile = () => {const link = document.createElement('a');link.href = this.pathUrl;link.download = 'document.pdf';link.click(); };
这样,用户就可以方便地下载文档。