这是我学习前端以来的第一次面试,挂在了二面实现一个具体项目需求上面;有遗憾,也有收获,总体感觉还是收获更大,知道了大厂面试的流程是怎么个样子,为今后的面试提供了宝贵的经验 ;同时也意识到一定要多刷面试题,这不仅仅是为了面试,更是能够拓宽知识面;平时也一定要自己亲手写代码,并且保证效率.
笔试题我并没有做的非常好,尤其是react实现组件封装,本来可以花更多的时间去实现要求的,可是受到了不可抗力因素的影响,实现需求的解决方案是想到了的,知道需要使用哪些api,但是很多代码都并不是自己手写的,而是先百度借鉴了一番;
当一开始收到字节的邀请面试邮件时,我因为怕误操作就没有点开来看,结果在第二天第一轮面试前十分钟才看到邮件说要添加hr的微信,当时瞬间就慌了,以为已经失去了这一次的面试机会,幸好等到了面试官的视频面试邀请;面试官非常的亲切,会用疑问来提示我的错误,此外,他也会对我的一些解答进行追问,问我还有其他的答案,其他的解决方案;总体上对于面试官的问题我都能回答两个点及以上,并且当场写代码也可以基本实现要求,只是有一些
属性会忘了怎么拼写
(vscode的自动补全给惯的),然后有一些问题给出了自己的答案却并没有给出理由
,有一些回答也是因为不是非常清楚随便猜,没有跟面试官说这个问题不是非常熟悉理解,之前没有去想过之类的回答
;一面是考察的基本上都是基础
,我在面试前也刷了面试题
,所以总体让面试官还是满意的,在最后一个环节面试官问我还有什么问题要问的时候,我问他公司前端开发的人数以及今后如果入职的晋升,结果他说他只能解答技术上的问题,其他的问题要问hr;面试持续了45分钟左右,面试完就安排了两个小时后的二面
二面以为就是hr面,结果还是技术面,并且没有让我自我介绍,一上来就是让我实现一个九宫格;面试官让我先实现一个每个格子都是正方形的九宫格,接着实现一个全屏幕正方形的九宫格;我先后使用了table,div来基本实现,不过感觉面试官都不是非常满意,当我提出使用栅格布局来实现时,面试官说栅格布局考虑到兼容性不可以使用;接着让我实现从后台请求数据,对应到九宫格的哪一个数字,那么该数字的背景就标红,我先说出了我的思路,然后就开始用代码实现,结果因为忘了js的一个api,导致代码写了很久,网络请求使用axios也被面试官说我写错了;整场面试持续了四十分钟,以写代码为主,总体表现是不及格的,我并没有使用面试时的网站来写代码,而是让面试官允许我用vscode,结果还是因为
代码写的慢
,js基础知识部分不熟悉
,异步网络请求不熟悉
,导致二面直接终结了我实习的机会。
所有笔试和面试都是在网络上进行
笔试有三道题
给出了六张图片,要求制作出指定静态页面,使用响应式布局,并且要适配各种分辨率的移动端屏幕
我给出的方案是使用媒体查询,根据的是google浏览器所列出的几种手机类型来进行适配
分别使用react和vue来封装一个多选框组件,要求要有一个全选框
因为我学的框架是vue,所以用vue封装的还算顺利,然而我由于从来没有接触过react,所以马上看B站视频恶补了一下,然后github了一个类似代码改了一下样式,并没有实现全选框功能
使用CSS实现dialog
实现思路步骤
position:fixed;bottom:-50px
把dialog会话框隐藏在页面之外onclick="toggleDialog(true)
,同理监听dialog上关闭按钮事件,传值falsetransition
来过渡,会话框关闭使用animation来进行进行过渡源码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>弹框动画</title>
<style>
button {
padding: 7px 10px;
border: none;
outline: none;
}
.open-btn {
background-color: #00bfff;
color: #fff;
border-radius: 3px;
box-shadow: 0px 1px 5px #808080;
}
.open-btn:hover{
box-shadow: 0px 2px 5px #808080;
}
.ripple-btn .waves-animation {
position: absolute;
border-radius: 50%;
width: 25px;
height: 25px;
opacity: 0;
background: rgba(255, 255, 255, 0.3);
transition: all 0.7s ease-out;
transition-property: transform, opacity, -webkit-transform;
-webkit-transform: scale(0);
transform: scale(0);
pointer-events: none;
}
.dialog {
width: 350px;
border-radius: 3px;
position: fixed;
bottom: -50px;
right: 30px;
box-shadow: 0px 0px 15px #dcdcdc;
opacity: 0;
visibility: hidden;
}
.content {
padding: 16px 12px;
font-size: 12px;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
margin-right: 10px;
padding: 5px 0 7px 0;
}
.dialog-footer > button:nth-child(1) {
margin-right: 10px;
background: none;
color: #00bfff;
}
.dialogslipUp {
transition: 1s;
width: 350px;
border-radius: 3px;
position: fixed;
bottom: 250px;
right: 30px;
box-shadow: 0px 0px 15px #dcdcdc;
opacity: 0.8;
z-index: 2000;
}
.dialogslipBottom {
/* transition: 0.5s; */
width: 350px;
border-radius: 3px;
position: fixed;
bottom: -50px;
right: 30px;
box-shadow: 0px 0px 15px #dcdcdc;
opacity: 0;
animation-name:dialogFaceSlipToBottom;
animation-duration: 1s;
}
/* 会话框消失动画 */
@keyframes dialogFaceSlipToBottom{
0%{
bottom: 250px;
opacity: 1;
}
25%{
bottom: 300px;
opacity: 0;
}
50%{
bottom: 450px;
}
75%{
bottom: 100px;
}
100%{
bottom: -50px;
}
}
</style>
</head>
<body>
<!-- 打开会话框按钮 -->
<button class="open-btn ripple-btn" onclick="toggleDialog(true)">SHOW AGAIN</button>
<div class="dialog" id="dialog">
<div class="content">
This could be a great way to display an ad using Materialize!
</div>
<hr />
<div class="dialog-footer">
<!-- 会话框关闭 -->
<button onclick="toggleDialog(false)" id="closed" class="ripple-btn">No THANKS</button>
<button class="open-btn">YES PLEASE</button>
</div>
</div>
</body>
<script type="text/javascript">
function toggleDialog(show) {
var animationClass = show ? "slipUp" : "slipBottom";
var closed =document.getElementById('closed')
var animation = function () {
dialog.className = "dialog" + animationClass;
};
if(animationClass === "slipBottom"){
closed.setAttribute('style','background-color:#dcdde1;')
}
else if(animationClass==="slipUp"){
closed.style.background='#fff';
}
setTimeout(animation, 100);
}
// 点击出现水波纹
document.addEventListener(
"DOMContentLoaded",
function () {
var duration = 750;
// 样式string拼凑
var forStyle = function (position) {
var cssStr = "";
for (var key in position) {
if (position.hasOwnProperty(key))
cssStr += key + ":" + position[key] + ";";
}
return cssStr;
};
// 获取鼠标点击位置
var forRect = function (target) {
var position = {
top: 0,
left: 0,
},
ele = document.documentElement;
"undefined" != typeof target.getBoundingClientRect &&
(position = target.getBoundingClientRect());
return {
top: position.top + window.pageYOffset - ele.clientTop,
left: position.left + window.pageXOffset - ele.clientLeft,
};
};
var show = function (event) {
var pDiv = event.target,
cDiv = document.createElement("div");
pDiv.appendChild(cDiv);
var rectObj = forRect(pDiv),
_height = event.pageY - rectObj.top,
_left = event.pageX - rectObj.left,
_scale = "scale(" + (pDiv.clientWidth / 100) * 10 + ")";
var position = {
top: _height + "px",
left: _left + "px",
};
(cDiv.className = cDiv.className + " waves-animation"),
cDiv.setAttribute("style", forStyle(position)),
(position.transform = _scale),
(position.opacity = "1"),
(position["transition-duration"] = duration + "ms"),
(position["transition-timing-function"] =
"cubic-bezier(0.250, 0.460, 0.450, 0.940)"),
cDiv.setAttribute("style", forStyle(position));
var finishStyle = {
opacity: 0,
"transition-duration": duration + "ms",
"-webkit-transform": _scale,
"-moz-transform": _scale,
"-ms-transform": _scale,
"-o-transform": _scale,
top: _height + "px",
left: _left + "px",
};
setTimeout(function () {
cDiv.setAttribute("style", forStyle(finishStyle));
setTimeout(function () {
pDiv.removeChild(cDiv);
}, duration);
}, 100);
};
document.querySelector(".ripple-btn").addEventListener(
"click",
function (e) {
show(e);
},
!1
);
},
!1
);
</script>
</html>
因为应聘的岗位对react框架更加的侧重,而我之前做的项目使用的框架都是vue,所以在介绍的时候我是这样说的:我开发过XXX和XX这两个项目,虽然用到的框架都是vue,但是我认为这里所要求的个人能力特质都是相同的,都需要对HTML,CSS以及JS有一定程度的了解,并且熟悉前后端分离开发;接着我还讲了平时对于HTML,CSS以及JS的笔记以及示例代码积累非常多
回答:
垂直居中我了解几种,首先我在平时项目当中最经常用到的就是display:flex
了,如果要对某一个元素进行垂直居中,那么就在父元素上使用
display:flex;
justify-content:center;
align-items:center;
当然也会用到position:absolute
,它是直接在要垂直居中的元素上使用即可
position:absolute;
left:50%;
top:50%;
transform:translate(-50%,-50%)
也可以
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
margin:aut
如果是知道元素宽高的情况下,可以
width:200px;
height:200px;
position:absolute;
top:50%;
left:50%;
margin-left:-100px;
margin-top:-100px;
JS实现也可以作为一个了解
let HTML=document.documentElement
winW=HTML.clientWidth;
winH=HTML.clientHeight;
boxW=box.offsetWidth;//box是要居中元素的id
boxH=box.offsetHeight;
box.style.position='absolute';
box.style.left=(WinW-boxW)/2+'px'
box.style.top=(WinH-boxH)/2+'px';
1:块级元素独占一行,而行内元素不行
2:块级元素可以设置宽高并且会自动填充满父元素,而行内元素不行
3:块级元素可以设置margin和padding,而行内元素不行
display:block;
-----可以把行内元素转化为块级元素
display:inline-block
------把行内元素转换为行内块元素,虽然不能独占一行,但可以设置宽高
display:none
--------让元素消失,不占用页面位置
1:let和const是ES6才有的api
2:let和const声明的是块级作用域,比如{},if以及for,而var的作用域是全局,举一个例子:
for(let i=0;i<3;i++){
console.log(i)
}
console.log(i)
因为i是用let声明在for块级作用域里面,所以在for循环外面打印i就会提示错误,表示i没有被定义
如果使用var声明的话,在for块级作用域外面依旧可以访问到i,虽然输出的范围是0~2之间,但是循环还会再运算一次i=i+1
3:var存在声明提升
首先我们来看一下使用三种变量声明方式去声明一个变量,并不赋值,结果会是怎样
浏览器输出:
实际代码输出:
浏览器调试台只有let会打印出undefined,剩下两个都是直接报错;而使用实际代码,let和var输出结果都是undefined,const直接报错,因为const在一开始声明的时候就要马上初始化赋值,否者就会报错
接着我们来了解一下作用域:作用域在ES5是只有全局作用域和函数作用域两种,而且如果在函数内部声明的变量,名字与全局变量相同,那么函数就会根据就近原则接收函数内部的变量
那么什么是声明提升呢?
Javascript引擎的工作机制是先预解析一遍代码,获取所有被声明的变量和函数声明,然后再一行一行的执行,这就使得所有用var声明变量的语句,都会提升到代码的头部,这就是声明提升
正常情况下,我们直接打印一个没有声明和定义的变量,那么就会报错
而由于var的声明提升,结果却发生了变化,第一次输出打印出来了undefined,说明变量d在这个时候已经被声明了但是没有赋值;
而如果使用let的话,就会直接报错
共同点:都不可以重复声明,但是除了const,都可以再次赋值
4:var具有全局作用域和函数作用域,并没有块级作用域
参考:ES6中let,var和const的区别,var声明与变量提升
for(var i=0;i<3;i++){
setTimeout(function(){
console.log(i)
},1000)
}
<style>
div{
width:0;
height:0;
border-top:10px solid red;
border-bottom:10px solid transparent;
border-left:10px solid transparent;
border-lright:10px solid transparent
}
</style>
<body>
<div></div>
</body>
transparent
属性了<style>
div{
width: 50px;
height: 50px;
background-color: teal;
animation-name: cicle1;//设置关键帧的名字
animation-duration: 1s;//设置完成一次动画的时间
animation-iteration-count: infinite;//设置动画无限执行
animation-timing-function: linear;//设置过渡速度保持稳定
}
@keyframes cicle1 {
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div></div>
</body>
!important
>内联选择器(行内样式)
>id选择器
>类选择器|属性选择器|伪类选择器
>元素选择器(标签)
>*(通配符)
规则 | 权重 |
---|---|
行内样式 | 1000 |
id选择器 | 100 |
类选择器 | 10 |
标签 | 1 |
* | 0 |
<style>
div{
width: 100px;
height: 100px;
background-color: lawngreen;
}
.red{
background-color: red;
}
.blue{
background-color: blue;
}
</style>
</head>
<body>
<div class="red blue"></div>
</body>
当两个选择器的权重相同时,按照选择器的先后顺序来进行规则,后面的选择器样式会覆盖前面选择器的样式
,所以div的背景颜色是蓝色
如果此时再加一个id选择器的话,结果又会不同
typeof undefined
和typeof null
的值分别是什么box-sizing:content-box
和box-sizing:border-box
的区别position
都有哪些值,有哪些是脱离了文档流,他们的定位原点在哪?padding
来撑<style>
.box{
width:25%;
padding-top:25%;//高度继承宽度
height:0;//避免div里面内容把正方形撑开
}
</style>
<body>
<div class="box"></div>
</body>
<style>
.box{
width:25%;
height:25vw;//vw是相对于视口的宽度,1vw=1% viewport width
background:#ccc;
}
</style>
<body>
<div class="box"></div>
<body>
更多方法参考:正方形自适应的几种方法
使用nth-child(odd)和nth-child(even)
table{
border: 1px solid #999;
border-collapse: collapse;//去除td之间的间隔
}
tr:nth-child(odd){//管理偶数行
backgroundcolor:red;
}
tr:nth-child(even){//管理奇数行
backgroundcolor:green;
}
使用nth-child(2n+1)和nth-child(2n)
table{
border:1px solid #999;
border-collapse:collapse;
}
tr:nth-child(2n+1){//管理偶数行
background-color:green;
}
tr:nth-child(2n){//管理奇数行
background-color:red;
}
第一种方法的奇数偶数计数是从th开始的,第二种方法的奇数偶数行计数是从tr开始的
基本类型:String Number Boolean Undefined Null Symbol
引用类型:Object Function Array
实现一个可以自适应手机屏幕的正方形九宫格,并且实现从后台请求数据,如果数据对应上了九宫格的某一个数字,该数字的背景就变红的随机抽奖demo