前端面试记录

99 阅读9分钟

整理一下面试官问到的一些问题

  1. css中position: static的用法,有没有用过
static跟fixed最大的区别应该是static没有脱离文档流?
真的没用过欸,有没有谁能告诉我啊,哭。

absolute	
生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。

元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。

fixed	
生成绝对定位的元素,相对于浏览器窗口进行定位。

元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。

relative	
生成相对定位的元素,相对于其正常位置进行定位。

因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。

static	默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。

inherit	规定应该从父元素继承 position 属性的值。
  1. rem和em
em:
参考物是父元素的font-size,具有继承的特点。浏览器默认字体是16px,整个页面内1em不是一个固定的值。
字体大小同样都是1.5em,但是效果却截然不同,按照W3C提供的公式,我们可以计算下: class为id1的div字体大小继承自父元素body:16px*1.5em = 24px class为id2的div字体大小继承自父元素id1:24px*1.5em = 36px class为id3的div字体大小继承自父元素id2:36px*1.5em = 54px

rem是CSS3新增的一个相对单位,但相对的只是HTML根元素。通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。
  1. 在移动端布局时出现边框消失该怎么办
-> 我没搞太懂,因为没遇到过,面试官点拨了一下,建议用伪元素画边框
  1. vw和vh
vm、vh、vmin、vmax是一种视窗单位,也是相对单位。它相对的不是父节点或者页面的根节点。而是由视窗(Viewport)大小来决定的,单位 1,代表类似于 1%。 视窗(Viewport)是你的浏览器实际显示内容的区域—,换句话说是你的不包括工具栏和按钮的网页浏览器。
vw:视窗宽度的百分比(1vw 代表视窗的宽度为 1%)
vh:视窗高度的百分比
vmin:取当前Vw和Vh中较小的那一个值
vmax:取当前Vw和Vh中较大的那一个值

  1. 不同平台适配分辨率的方法
-> 我就回答用过bootstrap和element-ui,其他简单的场景一般自己手写@media适配
  1. vue的生命周期?发送时一般会在哪个生命周期?
beforeCreate
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

created
在实例创建完成后被立即调用。
在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
如果要在第一时间调用methods中的方法,或者操作data中的数据,可在此钩子中进行操作。
需要注意的是,执行此钩子时,挂载阶段还未开始,$el 属性目前不可见。
此时,可以进行数据请求,将请求回来的值赋值给data中的数据。

beforeMount
在挂载开始之前被调用,此时模板已经编译完成,只是未将生成的模板替换el对应的元素。
在此钩子函数中,可以获取到模板最初始的状态。
此时,可以拿到vm.$el,只不过为旧模板

mounted
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
在该钩子函数中的vm.$el为新模板。
执行完该钩子函数后,代表实例已经被完全创建好。
如果要在第一时间,操作页面上的dom节点时,可以在此钩子函数中操作

beforeUpdate
数据更新时调用,发生在虚拟 DOM 打补丁之前。此时数据已经更新,但是DOM还未更新

updated
数据更改导致DOM重新渲染后,会执行该钩子函数。
此时数据和dom同步。

beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用。
可以在该钩子函数中,清除定时器。

destroyed
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除。

  1. vue父子组件通信
props, $emit, $attrs, $listeners, $parent, $children
感觉这样回答不是很好,应该补充上单向数据流之类的?
  1. 简述一下vue中的双向数据绑定是怎么实现的
v-model:
通过该指令,可以在表单元素上实现双向数据绑定
v-model本质上是语法糖,可以用简单的一个指令实现监控输入和绑定属性两个功能。
<input type="text" v-model="msg" />
<input type="text" @input="msg = $event.target.value" :value="msg" />
  1. 有没有用过插槽
我当时就回答只写过简单的练习,没用过复杂的,真想打死我自己...不过确实是没怎么想起来。

插槽:
现有父组件Parent.vue和子组件child.vue
父组件中使用插槽:
<child>
    写上你要传递给子组件的结构,比如<p>xxxxx</p>啥的
<child/>

子组件中准备插槽模板:
<div class='这是一个子组件'>
    这里有一堆其他的标签,比如<ul><li></li></ul>啥的
    <slot></slot>
</div>

到了最终编译的时候,父组件会变成:
<div class='这是一个子组件'>
    这里有一堆其他的标签,比如<ul><li></li></ul>啥的
    写上你要传递给子组件的结构,比如<p>xxxxx</p>啥的
</div>
  1. websocket
没用过,面试官很亲切得讲解了一下,自己回来又查了一下:
网上就有相关介绍的文章
-> http://www.ruanyifeng.com/blog/2017/05/websocket.html
  1. 服务器怎么判断客户端的权限,决定是否展示内容
我就随口说(我是真的菜,脑子一片空白,愣是思考了好久才反应过来),cookie和session吧...
  1. vue路由被设置成history之后会怎么样?
当时没想起来...

路径中不会显示很丑的哈希符号#
种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,
当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。

所以,要在服务端增加一个覆盖所有情况的候选资源:如果 URL匹配不到任何静态资源,则应该返回同一个 index.html 页面,
这个页面就是你 app 依赖的页面。
  1. h5新增的内容
当初学h5这块的时候,有过前面css3的经验,应该就是基本结构没变,多了一些标签什么的,需要用的时候直接查文档应该就能上手来着,结果昨天面试就掉坑里了。我自己就只说了新增的一些语义化标签,header,section,article,video什么的,连canvas都忘了。哎。

面试的公司好像要用到svg比较多,面试官又和蔼可亲地跟我说了一些svg的问题...
/********
主要是因为‘SVG DOM 中的每个元素都是可用的,可以为某个元素附加 JavaScript 事件处理器’这个特性,如果是做工程一类的需要动态显示和控制某些指标的管理系统的话,用svg应该会比较方便。
*********/

下面简单总结一下canvas和svg吧,具体其实应该就是会用就可以,但是有总结在面试沟通的时候会方便一些吧。
canvas:
1. 本身没有绘制能力,绘图过程由js完成
2. js获取canvas元素
3. 获取context对象
4. 绘制路径
5. 填充颜色

svg:
1. SVG 指可伸缩矢量图形 (Scalable Vector Graphics)
    -> SVG 图像在放大或改变尺寸的情况下其图形质量不会有损失
    -> SVG 是可伸缩的
    -> SVG 图像可在任何的分辨率下被高质量地打印
    -> SVG 可在图像质量不下降的情况下被放大
2. SVG 使用 XML 格式定义图形
    -> SVG 图像可通过文本编辑器来创建和修改
    -> SVG 图像可被搜索、索引、脚本化或压缩
    ->  SVG DOM 中的每个元素都是可用的,可以为某个元素附加 JavaScript 事件处理器
3. SVG 是万维网联盟的标准

其他H5特性:
- HTML5 Geolocation API 用于获得用户的地理位置。

- 拖放是 HTML5 标准的组成部分:任何元素都是可拖放的。

- 通过本地存储(Local Storage),web应用程序能够在用户浏览器中对数据进行本地的存储,优于cookie
    window.localStorage - 存储没有截止日期的数据
    window.sessionStorage - 针对一个 session 来存储数据(当关闭浏览器标签页时数据会丢失)
    
- HTML5 引入了应用程序缓存(Application Cache),这意味着可对 web 应用进行缓存,并可在没有因特网连接时进行访问

- Web worker 是运行在后台的 JavaScript,不会影响页面的性能。
    由于 web worker 位于外部文件中,它们无法访问下例 JavaScript 对象:
    window 对象
    document 对象
    parent 对象
    
- SSE Server-Sent 事件允许网页自动从服务器获得更新。

  1. 如何实现多组件之间的通信
这是面试官最后问的问题来着,前面搞忘了,补上...
我回答得不是很好,只说了vuex什么状态管理啥的,时间来不及了,我自己当时也记不清该怎么说。

Vuex是vue的状态管理工具,为了更方便的实现多个组件共享状态。
1. 安装组件
npm install vuex --save
2. 引入该库,在vue中使用
import Vuex from 'vuex';
Vue.use(Vuex);
3. 新建Store对象
const store = new Vuex.Store({
    //一些配置项
    state: {
        /***状态***/
        state: {
            count: 0
          }
    },
    getters: {
        /***state的计算属性***/
        doubleCount (state) {
            return state.count * 2;
          }
    },
    mutation: { 
        /***更改state的方法,组件要更改状态只能通过提交mutation来进行操作***/
        increment (state) {
          // 变更状态
          state.count++
        }
    }
})
4. 在Vue对象中配置
new Vue({
  store,
})
5. 在组件中使用
可以通过this.$store获得Store对象中的一系列配置
也可以通过辅助函数和解构赋值获取对象中的一系列属性
import { mapState, mapGetters,mapMutations  } from 'vuex';

例:通过提交mutation来更改state状态,使得整个流程更加清晰,避免直接更改状态带来的误解
this.$store.commit('increment');

  1. Vue.nextTick()
在页面重新渲染,DOM更新后,会立刻执行vm.$nextTick

可以作为promise使用
Vue.nextTick().then(() => {
  console.log(vm.$el.innerHTML); 
})
  1. 数组有哪些方法?怎么实现数组去重?
1. 利用对象属性的唯一性
const obj = {};
const arrTest = [1, 3, 6, 6, 7, 9, 7, 10];
const arrNew = [];
for (let i = 0; i<arrTest.length; i++) {
    if (obj[arrTest[i]]) {
        continue;
    }
    obj[arrTest[i]] = 'test';
    arrNew.push(arrTest[i]);
}
console.log(arrNew);

2. 利用Indexof方法
const arrTest = [1, 3, 6, 6, 7, 9, 7, 10];
const arrNew = [];
arrNew[0] = arrTest[0];
for (let i = 0; i<arrTest.length; i++) {
    if (arrNew.indexOf(arrTest[i])>=0) {
        continue;
    }
    arrNew.push(arrTest[i]);
}
console.log(arrNew);

3. 利用ES6的set
const arrTest = [1, 3, 6, 6, 7, 9, 7, 10];
const arrNew = [...new Set(arrTest)];
console.log(arrNew)
  1. 怎么解决ios移动端300ms点击延迟的问题
看网上的资料,有人建议用fastclik.js的

也有人说现在的浏览器,只要设置了viewport基本不会有这样的问题...