前端面试题(跟新中,情景题是本人在面试中被问到的)

css部分

CSS如何画⼀个三⻆形?原理是什么?

(1)利用边框绘制三角形

.triangle{
width: 0;
height: 0;
border-width:10px;
border-style: solid;
border-color: pink transparent transparent  transparent;
}

我们平时直接是border的复合写法,现在把他们分开就好

(2)利用伪元素绘制三角形

.triangle {
position: relative;
width: 0;
height: 0;
}
.triangle::before {
content: '';
position: absolute;
top: 0;
left: 0;
border-width: 10px;
border-style: solid;
border-color: pink transparent transparent transparent;
}

vue系列

你对SPA单页面的理解,它的优缺点分别是什么?

SPA (Single Page Application) 是一种 web 应用程序的架构模式,它的目标是在单个页面上提供更流畅的用户体验。传统的多页应用程序通过每次用户导航时重新加载整个页面,而 SPA 则是通过使用 JavaScript 动态地更新页面的部分内容,从而避免了页面的完全刷新。

在 SPA 中,初始页面加载时会下载一个包含所有必需资源(如 HTML、CSS、JavaScript 等)的单个页面。然后,通过 AJAX 或类似的技术进行异步数据交换,并根据用户的交互动态更新页面的特定部分,以实现页面的切换和内容的更新。

SPA 的一些主要特点和优势:

  1. 无刷新体验:SPA 可以在不刷新整个页面的情况下进行导航和内容更新,提供了更流畅的用户体验。

  2. 前后端分离:SPA 通常采用前后端分离的架构,由前端负责渲染视图和处理用户交互,后端提供 API 接口用于数据交换。

  3. 更快的加载速度:因为只需要加载初始页面一次,后续的页面操作和内容切换可以通过异步加载和更新,减少了网络请求的次数和数据的传输量。

  4. 良好的可维护性:由于前后端职责分离,开发团队可以更好地关注各自的领域,并且前端代码通常更易于管理和维护。

  5. 丰富的交互体验:SPA 可以通过动态加载内容、页面过渡效果、实时更新等功能提供更丰富的用户交互体验。

劣势:

  • 不利于搜索引擎的抓取
  • 首次渲染速度相对较慢

SPA⾸屏加载速度慢的怎么解决?

⾸屏时间( F irst Co n t e n t f u l Pa i n t ),指的是浏览器从响应⽤户输⼊⽹址地址,到⾸屏内容渲染完成 的时间,此时整个⽹⻚不⼀定要全部渲染完成,但需要展示当前视窗需要的内容。
加载慢的原因
  • ⽹络延时问题
  • 资源⽂件体积是否过⼤
  • 资源是否重复发送请求去加载了
  • 加载脚本的时候,渲染内容堵塞了

解决方案

  • 减⼩⼊⼝⽂件积
  • 静态资源本地缓存
  • UI框架按需加载
  • 图⽚资源的压缩
  • 组件重复打包
  • 开启GZip压缩
  • 使⽤S SR

1、减小入口文件体积

常⽤的⼿段是路由懒加载,把不同路由对应的组件分割成不同的代码块,待路由被请求的时候会单独打包路由,使得⼊⼝⽂件变⼩,加载速度⼤⼤增加。
v u e -r o u t e r 配置路由的时候,采⽤动态加载路由的形式。
routes:[
path: 'Blogs' ,
name : 'ShowBlogs' ,
component : () => import ( './components/ShowBlogs.vue' )
]
以函数的形式加载路由,这样就可以把各⾃的路由⽂件分别打包,只有在解析给定的路由时,才会加载 路由组件

2、 静态资源本地缓存

后端返回资源问题:
采⽤ H TTP 缓存,设置 C a c h e - C o n tr o l L a s t- M o d i fi e d Et a g 等响应头
采⽤ Se r v i c e Wo r k e r 离线缓存
前端合理利⽤ l o c a lSt o r a g e

3、UI框架按需加载 

在⽇常使⽤ U I 框架,例如 e l e m e n t- U I 、或者 a n t d ,我们经常性直接引⽤整个 U I
import ElementUI from 'element-ui'
Vue.use(ElementUI)

 但实际上我⽤到的组件只有按钮,分⻚,表格,输⼊与警告 所以我们要按需引⽤

import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui';
Vue.use(Button)
Vue.use(Input)
Vue.use(Pagination)
4、 组件重复打包
假设 A. j s ⽂件是⼀个常⽤的库,现在有多个路由使⽤了 A. j s ⽂件,这就造成了重复下载
解决⽅案:在 w e b p a c k c o n fi g ⽂件中,修改 C o m m o n s C h u n kPl u g i n 的配置。
minChunks: 3
m i n C h u n k s 3 表示会把使⽤ 3 次及以上的包抽离出来,放进公共依赖⽂件,避免了重复加载组件。
5、图⽚资源的压缩
图⽚资源虽然不在编码过程中,但它却是对⻚⾯性能影响最⼤的因素。
对于所有的图⽚资源,我们可以进⾏适当的压缩
对⻚⾯上使⽤到的 i c o n ,可以使⽤在线字体图标,或者雪碧图,将众多⼩图标合并到同⼀张图上,⽤以 减轻 h t t p 请求压⼒。

v-show和v-if

共同点

为true时,都会占据页面位置,当表达式为false时,都不会证据页面位置

区别
  1. 渲染方式v-show 是通过 CSS 控制元素的显示与隐藏,将元素的 display 样式属性设置为 none 或恢复为默认值来切换元素的可见性,dom元素依旧存在。而 v-if 是真正的条件渲染,根据表达式的值决定是否在 DOM 中创建、插入或移除元素。

  2. 初始渲染开销v-show 在初始渲染时,无论条件是 true 还是 false,都会立即渲染并保留元素的 DOM 结构,但使用 CSS 将其隐藏。相对而言,v-if 会根据条件渲染决定是否创建该元素的 DOM 结构。因此,如果元素在初始渲染时很少出现或经常更改条件,v-show 的初始渲染开销较低,而 v-if 可以减少初始渲染的开销。

  3. 切换开销v-show 在切换时只需改变元素的 CSS 显示属性,开销较小。而 v-if 在条件发生改变时需要销毁或创建元素的 DOM 结构,开销相对较大。

  4. 惰性渲染:由于 v-show 在初始渲染时始终保留元素的 DOM 结构,所以对于频繁切换的元素,v-show 可能更适合,因为它不需要重复创建和销毁 DOM。而 v-if 适用于一次性或较少变化的元素,可以节省内存。

  5. v-show由false变为true的时候不会触发组件的生命周期,v-if由false变为true的时候,会触发组件的beforeCreate,create,beforeMount,mounted钩子,由true变为false的时候触发组件的beforeDestory,destoryed方法

总的来说,如果需要频繁切换元素的可见性,并且元素在初始渲染时经常出现,可以使用 v-show。如果条件很少改变或元素在初始渲染时很少出现,可以使用 v-ifv-if有更高的切换消耗;v-show有更高的初始渲染消耗。

Vue中的$nextTick有什么作⽤?

什么是NextTick

官方定义为:在下次 D O M 更新循环结束之后执⾏延迟回调。在修改数据之后⽴即使⽤这个⽅法,获取更新后的 D O M。

意思是:当 Vue 进行数据更新时,DOM 并不会立即更新。Vue 使用异步更新队列将所有的数据变化收集起来,并在下一个 DOM 更新周期中进行批量更新,以提高性能和效率。而 $nextTick 则是用于在 DOM 更新完成后执行额外的操作。

$nextTick 方法有以下作用:

  1. DOM 操作同步化:在某些情况下,我们可能需要在更新 DOM 后立即操作或访问更新后的 DOM。例如,在使用 Vue 更新数据后,需要获取更新后的 DOM 尺寸、属性或对其进行手动操作时,可以通过 $nextTick 来确保这些操作在 DOM 更新后执行。

  2. 更新后的数据反映:当数据发生变化时,Vue 并不会立即更新相关的 DOM 元素。如果需要在数据更新后获取更新后的数据状态,可以使用 $nextTick 确保获取到最新的数据。比如,在修改数据后,希望获取更新后的数据值或状态,就可以使用 $nextTick 来确保数据已经更新。

  3. 异步操作处理:有时,我们需要执行一些异步操作,例如在数据更新后发送请求或执行其他耗时的操作。使用 $nextTick 可以确保在 DOM 更新完成后再执行这些异步操作,避免出现操作过早或 DOM 未更新的问题。

JavaScript系列

介绍一下undefined(了解)

undefined 是一个特殊的值,表示变量没有被显式赋值或不存在。

1、未定义的变量:如果在代码中使用了未声明的变量或访问了对象中不存在的属性,那么其值将会是 undefined。例如:

let x; // 未定义的变量
console.log(x); // 输出 undefined

const obj = { name: 'Alice' };
console.log(obj.age); // 输出 undefined,因为 age 属性不存在

2、函数返回值:如果函数没有明确返回值或者函数中没有 return 语句,那么函数的返回值将会是 undefined。例如:

function foo() {
  // 没有明确的返回值
}
const result = foo();
console.log(result); // 输出 undefined

3、可选参数:如果调用函数时未传递某个参数,那么该参数的值将会是 undefined。可以通过设置默认值来避免参数为 undefined。例如:

function greet(name) {
  console.log(`Hello, ${name}!`);
}

greet(); // 输出 Hello, undefined!

function greetWithDefault(name = 'Anonymous') {
  console.log(`Hello, ${name}!`);
}

greetWithDefault(); // 输出 Hello, Anonymous!

4、检查未定义:可以使用严格相等运算符(===)将变量与 undefined 进行比较来检查变量是否为 undefined。例如:

let x;

if (x === undefined) {
  console.log('变量 x 是未定义的');
}

说说JavaScript中的数据类型?仓储上的差别

分为俩种数据类型:基本数据类型和复杂数据类型

基本数据类型:Number,String,Bollean,Undefined,null,Symbol

引用数据类型:Object,Array,Function(还包括DateRegExpMapSet等内置函数)

存储区别:基本数据类型存储在栈中,引用数据类型的存储与堆中。(引用类型数据存放在堆中,每个堆内存对象都有对应的引用地址指向它,引用地址存放在栈中)

  • 声明变量时不同的内存地址分配:
    • 简单类型的值存放在栈中,在栈中存放的是对应的值
    • 引用类型对应的值存储在堆中,在栈中存放的是指向堆内存的地址
  • 不同的类型数据导致赋值变量时的不同:
    • 简单类型赋值,是生成相同的值,两个对象对应不同的地址
    • 复杂类型赋值,是将保存对象的内存地址赋值给另一个变量。也就是两个变量指向堆内存中同一个对象

判定数据类型的方法

1、typeof 是用来判断数据的类型 结果是内容全小写

typeof 100 'number'

typeof '123' 'string'

typeof true 'boolean;

typeof undefined 'undefined'

typeof function(){} 'function'

typeof null 'object'

typeof [] 'object'

typeof {} 'object'

2、instanceof 判断一个任意类型对象的具体类型

判断前面的是不是后面构造函数的实例 按照原型链 可以判定Array ,object

[] indtanceof Array   true

{} indtanceof Object  true ....

3、Object.prototype.toString.call(值) '[object Number]'

console.log(Object.prototype.toString.call(123));    //[object Number]
console.log(Object.prototype.toString.call('123'));    //[object String]
console.log(Object.prototype.toString.call(undefined));    //[object Undefined]
console.log(Object.prototype.toString.call(true));    //[object Boolean]
console.log(Object.prototype.toString.call({}));    //[object Object]
console.log(Object.prototype.toString.call([]));    //[object Array]
console.log(Object.prototype.toString.call(function(){}));    //[object Function]
console.log(Object.prototype.toString.call(null));    //[[object Null]]

4.constructor  

console.log("123".constructor === String); // true
console.log(123.constructor === Number); // true

性能优化

前端性能优化的方法有什么

  1. 压缩和合并文件:通过压缩和合并CSS、JavaScript和HTML文件,减少文件大小和请求次数,从而加快页面加载速度。

  2. 图片优化:使用适当的图像格式(如JPEG、PNG或WebP),并压缩图片以减小文件大小。还可以使用懒加载技术,延迟加载屏幕上可见的图片,减少初始加载时间。

  3. 使用CDN加速:将静态资源(如CSS、JavaScript和图片)存储在内容分发网络(CDN)上,使用户可以从离其最近的服务器获取数据,加快页面加载速度。

  4. 延迟加载和按需加载:将非关键和不可见的内容延迟加载,只在需要时动态加载。例如,延迟加载图片、滚动到可见区域再加载更多内容等。

  5. 避免重定向:过多的重定向会增加额外的请求时间。确保使用直接的URL连接,避免过多的重定向链。

  6. CSS和JavaScript优化:尽量减少CSS和JavaScript文件的数量和大小。可以使用工具进行压缩、合并和混淆代码,同时删除未使用的代码和注释以减小文件大小。

  7. 使用缓存:合理设置缓存策略,使重复访问的资源能够从缓存中获取,减少服务器请求。对于动态内容,可以使用客户端缓存技术(如LocalStorage)来保存临时数据。

  8. 响应式设计:采用响应式设计,使网站或应用程序适应不同屏幕尺寸和设备类型,提供更好的用户体验。

  9. 减少DOM操作:频繁的DOM操作会触发页面重新渲染,影响性能。通过批量处理DOM操作或使用虚拟DOM技术(如React、Vue等)来减少对DOM的直接操作。

  10. 性能监测和调优:使用工具进行性能监测和分析,识别潜在的性能瓶颈,并进行相应的优化调整。

  11. 脚本优化:减少重绘和回流、缓存DOM选择与计算、缓存.length的值、尽量使用事件代理、尽量使用id选择器、touch事件优化.尽量改变class而不是style,使用classList代替

git问题

常用的命令有那些

启动

一个git项目的初始有两个途径,分别是:

  • git init [project-name]:创建或在当前目录初始化一个git代码库
  • git clone url:下载一个项目和它的整个代码历史

日常基本操作

  • git init 初始化仓库,默认为 master 分支
  • git add . 提交全部文件修改到缓存区
  • git add <具体某个文件路径+全名> 提交某些文件到缓存区
  • git diff 查看当前代码 add后,会 add 哪些内容
  • git diff --staged查看现在 commit 提交后,会提交哪些内容
  • git status 查看当前分支状态
  • git pull <远程仓库名> <远程分支名> 拉取远程仓库的分支与本地当前分支合并
  • git pull <远程仓库名> <远程分支名>:<本地分支名> 拉取远程仓库的分支与本地某个分支合并
  • git commit -m "<注释>" 提交代码到本地仓库,并写提交注释
  • git commit -v 提交时显示所有diff信息
  • git commit --amend [file1] [file2] 重做上一次commit,并包括指定文件的新变化

分支操作

  • git branch 查看本地所有分支
  • git branch -r 查看远程所有分支
  • git branch -a 查看本地和远程所有分支
  • git merge <分支名> 合并分支
  • git merge --abort 合并分支出现冲突时,取消合并,一切回到合并前的状态
  • git branch <新分支名> 基于当前分支,新建一个分支
  • git checkout --orphan <新分支名> 新建一个空分支(会保留之前分支的所有文件)
  • git branch -D <分支名> 删除本地某个分支
  • git push <远程库名> :<分支名> 删除远程某个分支
  • git branch <新分支名称> <提交ID> 从提交历史恢复某个删掉的某个分支
  • git branch -m <原分支名> <新分支名> 分支更名
  • git checkout <分支名> 切换到本地某个分支
  • git checkout <远程库名>/<分支名> 切换到线上某个分支
  • git checkout -b <新分支名> 把基于当前分支新建分支,并切换为这个分支

 远程同步

  • git fetch [remote] 下载远程仓库的所有变动
  • git remote -v 显示所有远程仓库
  • git pull [remote] [branch] 拉取远程仓库的分支与本地当前分支合并
  • git fetch 获取线上最新版信息记录,不合并
  • git push [remote] [branch] 上传本地指定分支到远程仓库
  • git push [remote] --force 强行推送当前分支到远程仓库,即使有冲突
  • git push [remote] --all 推送所有分支到远程仓库

撤销

  • git checkout [file] 恢复暂存区的指定文件到工作区

  • git checkout [commit] [file] 恢复某个commit的指定文件到暂存区和工作区

  • git checkout . 恢复暂存区的所有文件到工作区

  • git reset [commit] 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变

  • git reset --hard 重置暂存区与工作区,与上一次commit保持一致

  • git reset [file] 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变

  • git revert [commit] 后者的所有变化都将被前者抵消,并且应用到当前分支

 存储操作

你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作,但又不想提交这些杂乱的代码,这时候可以将代码进行存储

  • git stash 暂时将未提交的变化移除

  • git stash pop 取出储藏中最后存入的工作状态进行恢复,会删除储藏

  • git stash list 查看所有储藏中的工作

  • git stash apply <储藏的名称> 取出储藏中对应的工作状态进行恢复,不会删除储藏

  • git stash clear 清空所有储藏中的工作

  • git stash drop <储藏的名称> 删除对应的某个储藏

这个是git切换分支导致代码丢失找回链接,面试当然不问,但是在实际开发中会用到,为什么,因为我遇到了,当时慌啊 

情景题

有一个按钮作用是点击上传文件,前端应该怎么做可以避免我如果点击多次就上传多次的

  1. 禁用按钮:在首次点击上传后,立即禁用上传按钮,直到上传完成或出现错误时再启用。这样可以防止用户连续点击触发多次上传。

  2. 显示上传状态:在上传过程中,可以显示一个上传状态的提示,告知用户当前正在进行上传操作。可以使用loading动画或进度条等方式显示上传进度,增加用户的等待感知。

  3. 阻止重复点击事件:在按钮点击事件触发后,立即取消后续的点击事件。可以通过在点击事件处理函数中添加一个标志位,来判断是否已经有一次上传操作正在进行,若有,则忽略后续的点击事件。

  4. 添加延迟效果:可以在点击事件触发后,增加一个短暂的延迟时间,在延迟结束前禁用按钮。这样可以确保只有第一次点击会触发上传操作,后续的点击会被忽略。

  5. 提示并阻止重复操作:在上传开始之前,可以弹出一个提示框告知用户已经有一个上传任务正在进行,请等待上传完成后再进行下一次操作。同时,可以阻止再次触发上传事件,或者给予相应的提示并阻止用户重复点击

前端从服务器拿到图片,怎么不下载的情况下在前端页面中查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

起名时在学Aiifox

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值