你的html真的学好了吗? 要不要给你的html+css来场小测验呢?你的基础算法刷到位了嘛?大厂的面试题你要不要来试一试?
话不多说 上题
前端基础面试题:手风琴的制作
简易手风琴的制作,算是一道质量基础题,请用css完成:
当鼠标移动到键盘时产生如下动态效果
思路喔 看起来也不是很难 不就是悬浮动画嘛
我们先来分析一下,我们需要六块不同颜色的矩形条块,效果是当鼠标移至某一块时,会展开。想想解决办法吧~
-
JavaScript动态调整
flex
属性
思路:
- 基础布局:使用CSS将所有列表项排列成水平的并排样式,初始宽度为相等。
- 事件监听器:使用JavaScript为每个列表项添加
mouseover
和mouseout
事件监听器。 - 悬停效果:在
mouseover
事件中,重置所有列表项的宽度,将悬停的列表项宽度增加。 - 恢复默认:在
mouseout
事件中,重置所有列表项的宽度到默认值。 不过用js会显得我们很暴力
-
CSS Grid
思路:
- Grid布局:使用CSS的Grid布局,将列表项排列成网格列。
- 基础样式:初始设置每个列表项占据相等的网格列宽度(1fr)。
- 悬停效果:当悬停在某个列表项上时,通过修改
grid-template-columns
属性,增加悬停项的网格宽度。 - 相邻项调整:使用CSS选择器来调整悬停项后的相邻项的宽度,使其缩小以给悬停项让出空间。
-
利用
focus
伪类
思路:
- 基础布局:使用CSS将所有列表项排列成水平的并排样式,初始宽度为相等。
- 可聚焦元素:为每个列表项添加
tabindex
属性,使其可聚焦。 - 悬停效果:使用
:focus
伪类,当列表项获得焦点时,增加其宽度。 - 相邻项调整:使用CSS选择器来调整获得焦点项后的相邻项的宽度,使其缩小以给获得焦点的项让出空间。
浮动布局
思路:
- 浮动布局:使用CSS的浮动布局,将所有列表项浮动排列在同一行。
- 基础样式:初始设置每个列表项的宽度相等,使用固定宽度(如600px / 6)。
- 悬停效果:当鼠标悬停在某个列表项上时,通过
:hover
伪类或JavaScript事件,增加该项的宽度。 - 相邻项调整:通过相邻选择器或JavaScript,缩小悬停项后面的相邻项的宽度,以给悬停项让出空间。
压轴 弹性布局
既是压轴 自然要比其他方法相对来说简单一点,弹性布局是我们的一位老朋友了,因为移动端的屏幕大小不一,我们使用弹性布局更适配。
- 首先 我们需要完成布局 对大家并不难
<ul class="accordion">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
是的没错 已经足够了
- ul开辟了一个全新的格式化上下文(不是让li元素变成块级喔),li默认是纵向排列的,然后我们需要想想ul怎么横向排列 没错 就是弹性(子元素默认在一行 不会换行)
- 让它倒下来了 后面自然就好说了给大小、上颜色
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul,
li {
list-style: none;
}
.accordion {
display: flex;
width: 600px;
height: 200px;
}
.accordion li {
flex: 1;
cursor: pointer;
line-height: 200px;
color: #fff;
}
.accordion li:nth-child(1) {
background-color: #f66;
}
...//剩余五个仿照第一个就好了
- 可以看见已经完成了
- 接下来就是动起来了 所以我么容易想到
transition
,大家看见了我们设置了flex,因此我们只需要再加亿点
.accordion li{
transition: flex 500ms;//设置延迟 更丝滑
}
.accordion li:hover {
flex: 2;//比重为两倍 占宽更多
}
请欣赏
拍平多维数组
arr=[1,[2,[3,4,[5,[6]]]]] 将arr输出为一维数组
很容易我们就能想到递归方法
- 调用自身来处理更小的子问题。flatten(){}
function flatten(arr) {
let result=[]
//len缓存了arr.length的值 arr是对象 每次循环读取arr.length耗时
for(let i=0,len=arr.length;i<len;i++){
// 如果是数组 递归
if(Array.isArray(arr[i])){
result=result.concat(flatten(arr[i]))
}else{
result.push(arr[i])
}
// 否则 加入数组
}
return result
}
console.log(flatten(arr));
-
初始化结果数组:
let result = [];
创建一个空数组result
,用于存储展平后的结果。
-
遍历输入数组:
for (let i = 0, len = arr.length; i < len; i++) { ... }
遍历输入数组arr
的每一个元素。- 使用
len
缓存arr.length
的值,避免每次循环重新计算长度,提升性能。
-
检查元素是否为数组:
if (Array.isArray(arr[i])) { ... }
判断当前元素arr[i]
是否为数组。
-
递归处理子数组:
result = result.concat(flatten(arr[i]));
如果当前元素是数组,则递归调用flatten
函数,将其展平,然后将展平的结果连接到result
数组。
-
处理非数组元素:
result.push(arr[i]);
如果当前元素不是数组,则将其直接加入result
数组。
我们进阶一下 换一种方法 去中厂
- 在js中 toString()方法不知道各位有没有了解过 他可以将数组转换为字符串,所以,不管他有几唯,我们直接可以一下拍扁。
- 但是拍扁后的是字符串,我们还需要将它转换为数组,怎么实现呢?
- 一种方法是将它转换为字符串数组,然后遍历转换成数字
- 我们知道 js中 Number() 和parseInt()都可以转换为数字,但也还有一种隐式转换 +"" 也可以
var arr =[1,[2,[3,4,[5,[6]]]]]
function flatten(arr) {
var strArr= arr.toString()//以逗号隔开的字符串
var numArr=strArr.split(',')
var result=[]
for (let i = 0,length=numArr.length; i < length; i ++) {
// 强制类型转换 Number()、 parseInt()、+
result.push( +numArr[i])
}
console.log(result);
// return
}
flatten( arr)
那么 我野心勃勃 直奔大厂
聊聊map
map
是一个数组方法,用于创建一个新数组,新的数组中的每个元素都是调用一次提供的函数后的结果。该方法按照原数组元素顺序依次处理元素,执行函数会被自动传入三个参数:当前元素值、当前索引值、数组本身。
懂了 来吧
-
将数组转换为逗号分隔的字符串:
- 将多维数组使用
toString()
方法转换为一个字符串,其中数组中的每个元素以逗号分隔。
- 将多维数组使用
-
将字符串分割为字符串数组:
- 使用
split(',')
方法将上一步得到的逗号分隔的字符串切割成一个字符串数组。
- 使用
-
遍历字符串数组并转换为数字数组:
- 使用
map
方法遍历字符串数组的每个元素。 - 对于每个字符串元素,使用类型转换操作将其转换为数字。
- 将这些转换后的数字组成一个新的结果数组。
- 使用
var arr =[1,[2,[3,4,[5,[6]]]]]
function flatten(arr) {
return arr.toString().split(',').map(function(item){
return +item
})
}
console.log(flatten(arr));
大厂欢迎各位 继续加油
总结
通过这几种方法,可以实现手风琴效果和多维数组拍平的问题。每种方法都有其适用场景和优缺点。理解这些实现方法和背后的思路,有助于解决类似的前端布局和算法问题,提升前端开发技能。继续学习和实践这些技术,将会为进入大厂面试做好充分的准备。不知各位能否留下小赞。