这么简单的面试你不会不懂吧?js手风琴+拍平数组

370 阅读6分钟

你的html真的学好了吗? 要不要给你的html+css来场小测验呢?你的基础算法刷到位了嘛?大厂的面试题你要不要来试一试?

话不多说 上题

前端基础面试题:手风琴的制作

简易手风琴的制作,算是一道质量基础题,请用css完成:

当鼠标移动到键盘时产生如下动态效果

image.png

思路喔 看起来也不是很难 不就是悬浮动画嘛

我们先来分析一下,我们需要六块不同颜色的矩形条块,效果是当鼠标移至某一块时,会展开。想想解决办法吧~

  • JavaScript动态调整flex属性

思路:

  1. 基础布局:使用CSS将所有列表项排列成水平的并排样式,初始宽度为相等。
  2. 事件监听器:使用JavaScript为每个列表项添加mouseovermouseout事件监听器。
  3. 悬停效果:在mouseover事件中,重置所有列表项的宽度,将悬停的列表项宽度增加。
  4. 恢复默认:在mouseout事件中,重置所有列表项的宽度到默认值。 不过用js会显得我们很暴力
  • CSS Grid

思路:

  1. Grid布局:使用CSS的Grid布局,将列表项排列成网格列。
  2. 基础样式:初始设置每个列表项占据相等的网格列宽度(1fr)。
  3. 悬停效果:当悬停在某个列表项上时,通过修改grid-template-columns属性,增加悬停项的网格宽度。
  4. 相邻项调整:使用CSS选择器来调整悬停项后的相邻项的宽度,使其缩小以给悬停项让出空间。
  • 利用focus伪类

思路:

  1. 基础布局:使用CSS将所有列表项排列成水平的并排样式,初始宽度为相等。
  2. 可聚焦元素:为每个列表项添加tabindex属性,使其可聚焦。
  3. 悬停效果:使用:focus伪类,当列表项获得焦点时,增加其宽度。
  4. 相邻项调整:使用CSS选择器来调整获得焦点项后的相邻项的宽度,使其缩小以给获得焦点的项让出空间。

浮动布局

思路:

  1. 浮动布局:使用CSS的浮动布局,将所有列表项浮动排列在同一行。
  2. 基础样式:初始设置每个列表项的宽度相等,使用固定宽度(如600px / 6)。
  3. 悬停效果:当鼠标悬停在某个列表项上时,通过:hover伪类或JavaScript事件,增加该项的宽度。
  4. 相邻项调整:通过相邻选择器或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;
}
...//剩余五个仿照第一个就好了
  • 可以看见已经完成了

image.png

  • 接下来就是动起来了 所以我么容易想到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)); 

大厂欢迎各位 继续加油

总结

通过这几种方法,可以实现手风琴效果和多维数组拍平的问题。每种方法都有其适用场景和优缺点。理解这些实现方法和背后的思路,有助于解决类似的前端布局和算法问题,提升前端开发技能。继续学习和实践这些技术,将会为进入大厂面试做好充分的准备。不知各位能否留下小赞。