前端还是一个年轻的行业,新的行业标准, 框架, 库都不断在更新和新增,正如赫门在 2015 深 JS 大会上的《前端服务化之路》主题演讲中说的一句话:“每 18 至 24 个月,前端都会难一倍”,这些变化使前端的能力更加丰富、创造的应用也会更加完美。所以关注各种前端技术,跟上快速变化的节奏,也是身为一个前端程序员必备的技能之一。

一、node.js 及项目工程化

1、遍历文件夹的所有文件

要熟悉node常用模块的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// nodejs使用的commonjs的语法,只能用require引入
const path = require("path");
const fs = require("fs");

const readDir = entry => {
const dirInfo = fs.readdirSync(entry);
dirInfo.forEach(dir => {
const fileLocation = path.join(entry, dir);
const info = fs.statSync(fileLocation);
if (info.isDirectory()) {
console.log(`dir:${fileLocation}`);
readDir(fileLocation);
} else {
console.log(`file:${fileLocation}`);
}
});
};

// 遍历当前文件夹下的所有文件
readDir(__dirname);

面试时注意:
为什么前端需要学习nodejs:使用 nodejs 可以做前端工程化、webpack、npm 包管理


2、nodejs 版本升级

为什么需要升级 node 版本?
webpack 打包速度更快,可以尝试升级 node 版本
nvm 升级
允许在电脑上安装多个 node 版本,可以任意切换

3、模块化的差异
AMD(require.js)、CMD(sea.js)、commonJS(nodejs)、ES6 module
AMD 依赖前置、CMD 依赖就近
commonJS 支持动态引入(可以根据不同逻辑引入不同内容),ES6 module 不支持动态引入(只能是静态引入)

4、图片上传到服务器的过程
图片如何为实现预览?(思路)
1)高版本浏览器

1
<input type="file" onchange="function(){}" /> <img src="base64" />

onchange 后使用 FileReader.readAsDataURL 将图片转化为 base64,再插入 img 的 src 中可以实现预览效果

2)兼容低版本浏览器

1
<input type="file" onchange="function(){}" /> <img src="url" />

onchange 触发时,让 input 通过表单的形式提交给后端,后端存储完会返回给图片 url,再在 img 中显示图片

5、token 存在 cookie 里,过期怎么处理?
跳转到登录页面

6、node 框架中的 mvc
model view controller
模型 视图 控制器
mvc 的理念
mvc、mvp、mvvm 的差异

7、mongodb 和 mysql 的优势
数据灵活采用 nosql 合适,如 mongodb
数据规范采用结构化数据库合适,如 mysql

8、less、sass、stylus、css
less 底层通过 js 做编译,sass 底层通过 ruby 做编译
可以定义变量,采用命名空间(解决 css 冲突,如 vue 中的 scoped 参数)与 css module

9、工程化上的按需加载
异步组件
import(‘a.js’).then()
react 中采用 reloadable.js 库

10、git 上的冲突如何解决
冲突产生:两人修改同一文件同一代码块
拉取最新代码,手动解决冲突,再提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
git init
git remote add origin git@github.com:iloveyou11/land_system_yanghao.git
git pull origin master
.gitignore
git add .
git commit –m “这里写下你自己的记录本次提交内容的信息”
git push origin master -f
//删除文件夹 git rm -r --cached target

//多人协作,分支开发,合并至主支:
git checkout -b mydev / git checkout -b mydev 新建并切换至分支
git add .
git commit –m / git commit –m -a“这里写下你自己的记录本次提交内容的信息”
git push (目前已经将本地代码全部提交至github上的分支)
git checkout master
git merge origin/mydev(将github上分支mydev的内容合并到master主枝)
git push (将master的内容也提交至线上)
git branch -d mydev(删除mydev分支)

11、设计模式
观察者模式、发布-订阅模式、工厂模式、代理模式、组合模式、适配器模式、单例模式、外观模式……
redux 中的 store——观察者模式
组合模式优于继承
单例模式

12、nodejs 中的 npm 与版本管理(package.lock,yarn.lock)
package.lock,yarn.lock 为版本锁,锁定同一版本
建议再项目中加上 lock 文件,否则上线后会遇到 npm 包版本变更带来的坑

13、webpack
建议读英文官方文档(国内翻译很慢而且不准确)
webpack4 比 webpack3 性能提高了 95%以上
api 级别发生了大量的变化
webpack 插件的原理、loader 的实现

14、后端环境搭建
nodejs+pm2(进程管理工具)

15、typescript
代码校验,类型约束——可以很好地提高代码质量

二、reactJS 常见问题讲解

1、redux 中间件的原理
action 和 store 中间(中间件)
action 到达 store 之前会走这个中间件,中间件可以将函数 action 转化为对象,再传递给 store
redux-saga、redux-thunk 等
如何对 dispatch 进行包装的?
看 github redux-thunk 源码
2、你会把数据统一放到 redux 中管理,还是共享的数据放到 redux 中管理
如果 redux、props、state 都存储数据,不方便定位问题
而且不方便扩展,可维护性差
建议使用 redux 存储全部数据即可
3、componentWillReceiveProps 的调用时机
props 改变时才会被调用,第一次传递 props 时是不会调用的
4、react 性能优化的最佳实践
pureComponent 适合的场景(自带 componentShouldUpdate,但是是浅比较)
使用 immutable.js 库和 pureComponent 做结合,可以非常完美的解决 react 的性能问题
5、虚拟 dom 是什么?为什么会提高代码性能
虚拟 dom 是 js 对象,比对 js 对象很快
dom diff 算法、key 值问题
6、webpack 中,是借助 loader 完成的 jsx 代码的转化,还是 babel
babel:preset-react
7、调用 setState 后,发生了什么?setState 是异步的,在什么时候遇到过坑
使用函数式调用,避免异步操作带来的各种坑
this.setState(()=>({
​ name:’Dell Lee’
}))
8、refs 的作用是什么?在什么业务场景下会使用到 refs
1、渲染图片完成后,获取宽和高
2、对 input/video/audio 需要控制时,例如输入框焦点、媒体播放状态
3、直接动画控制
4、集成第三方库
注意:如果能使用 props 实现,应该尽量避免使用 refs 实现
使用 ref 的正确方式:(应使用函数式写法,不要使用 ref=’abc’这样字符串的写法
9、高阶组件怎么理解,它本质是什么?
高阶组件:对组件进行包装,返回新的组件
原则:[组合优于继承]
react 的 hook?(建议看一下)
10、受控组件和非受控组件的区别
受控组件:组件的改变完全依赖于数据的变化
非受控组件:可以不需要设置它的 state 属性,而通过 ref 来操作真实的 DOM。
11、函数组件和 hooks
12、this 指向问题你一般怎么解决?
箭头函数、bind(this)——constructor 中
13、函数组件怎么做性能优化
函数组件,可以使用 Reacr.memo,拥有 shouldUpdate

1
2
3
React.memo(function(){
return <div>123123</div>
})

14、哪个生命周期发送 ajax?
componentDidMount 中
1、componentWillMount 在新版本 react 中已经废弃了
2、SSR 项目时,componentWillMount 要做服务器端数据的获取,因此不能被占用
15、SSR 的原理
借助虚拟 dom
16、react-saga 的设计思想是什么?什么是 sideEffects?
(冲击高薪可以看一下)
17、react、jquery、vue 是否可能共存在一个项目中?
每个只操作对应的 div,可以实现共存
18、组件是什么?类是什么?类被编译成什么?
模块:针对 webpack 打包工具而言
组件:页面的一部分
类:被编译后其实就是构造函数
19、你是如何跟着社区成长的?
如何主动学习新技术?
多看英文文档,看 react 官方团队的 twitter
20、如何避免 ajax 数据重新获取?
使用 react-redux 进行管理
21、react-router4 的核心思想是什么,和 3 有什么区别?
react-router4 中路由也变成了组件,如
22、reselect 是做什么使用的?
相当于计算属性(如 vue 中的 computed)
23、react-router 的基本原理,hashHistory、browserHistory
browserHistory 在前端不能单独配置,还需要在后端进行配置
hashHistory 不需要后端服务器配置,仅依赖前端即可
24、什么情况下使用异步组件?
reloadable 库——懒加载
import(‘./home/header’).then()
require.ensure
25、xss 攻击在 react 中如何防范
慎用 dangerouslySetInnerHTML 函数
26、immutable.js 和 redux 的最佳实践

三、Vue.js 常见问题讲解

1、vuex 是什么?怎么使用?哪种功能场景使用它?
vuex 是状态(数据)管理仓库,解决组件间状态共享的问题,强调集中式管理
2、导航钩子有哪些?它们有什么参数?

  • 全局导航钩子
    全局导航钩子主要有两种钩子:前置守卫、后置钩子,
    注册一个全局前置守卫:
1
2
3
4
5
6
7
const router = new VueRouter({ ... });
router.beforeEach((to, from, next) => {
// do someting
});
router.afterEach((to, from) => {
// do someting
});

这三个参数 to 、from 、next 分别的作用:
to: Route,代表要进入的目标,它是一个路由对象
from: Route,代表当前正要离开的路由,同样也是一个路由对象
next: Function,这是一个必须需要调用的方法,而具体的执行效果则依赖 next 方法调用的参数

  • 路由独享的钩子
    顾名思义,即单个路由独享的导航钩子,它是在路由配置上直接进行定义的:
1
2
3
4
5
6
7
8
9
10
11
const router = new VueRouter({
routes: [
{
path: '/file',
component: File,
beforeEnter: (to, from ,next) => {
// do someting
}
}
]
});
  • 组件内的导航钩子
    组件内的导航钩子主要有这三种:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。他们是直接在路由组件内部直接进行定义的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const File = {
template: `<div>This is file</div>`,
beforeRouteEnter(to, from, next) {
// do someting
// 在渲染该组件的对应路由被 confirm 前调用
},
beforeRouteUpdate(to, from, next) {
// do someting
// 在当前路由改变,但是依然渲染该组件是调用
},
beforeRouteLeave(to, from ,next) {
// do someting
// 导航离开该组件的对应路由时被调用
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
最后是完整的导航解析流程:
导航被触发
在失活的组件里调用离开守卫
调用全局的 beforeEach 守卫
在重用的组件里调用 beforeRouteUpdate 守卫
在路由配置里调用 beforEnter
解析异步路由组件
在被激活的组件里调用 beforeRouteEnter
调用全局的 beforeResolve 守卫
导航被确认
调用全局的 afterEach 钩子
触发 DOM 更新
在创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数

3、v-model 是什么?vue 标签怎么绑定事件?
4、vue 路由懒加载
5、vue-loader
6、插槽
7、vue 的虚拟 dom
8、vue 的 keep-alive
9、swiper 插件从后台获取数据没问题,css 代码没问题,但是图片不动,应该怎么解决?
主要原因:swiper 提前初始化了,而这个时候,数据还没有完全加载
1)vue 中提供了 nextTick 方法专门解决此类问题
2)修改 swiper 的配置:observer:true,observeParents:true

四、页面布局及设备适配

1、元素水平垂直剧中、图片水平垂直居中、清除浮动、自适应布局
1)单行文本居中:
水平居中:text-align:center;
垂直居中:line-height:XXpx; /line-height 与元素的 height 的值一致/
2)多行文本居中

  • 使用 display:table 来实现
    主要实现代码:
    display: table 使块状元素成为一个块级表格;
    display: table-cell;子元素设置成表格单元格;
    vertical-align: middle;使表格内容居中显示,即可实现垂直居中的效果;
  • 使用 absolute 与 transform 配合实现
    position:absolute; 首先给文本绝对定位;
    left:50%;top:50%;transform:translate(-50%,-50%);
    让文本距离盒子左边和上边分别为 50%,再用 transform 向左(上)平移它自己宽度(高度)的 50%,也就达到居中效果了。
  • 使用 flex 实现
    主要实现代码:
    display: flex;设置 display 属性的值为 flex 将其定义为弹性容器
    align-items: center;定义项目在交叉轴(纵轴)上如何对齐,垂直对齐居中
    justify-content: center; 定义了项目在主轴上的对齐方式,水平对齐居中

2、清除浮动

  • 添加元素及其 clear 属性
  • 父元素设置伪元素清除浮动
  • 父元素设置 overflow:hidden
  • 父元素设置一定的高度 height
  • 父元素设置 display: table

3、IE6 兼容
IE6 7 下常见 CSS 兼容性处理:

  • H5 标签不兼容,比如 header,section,footer 等
1
2
3
4
5
6
7
8
9
10
11
<style type="text/css">
header {
display: block; //自定义标签默认为inline元素,需手动转成block,不然宽高不起作用
width: 100px;
height: 100px;
background: red;
}
</style>
<script type="text/javascript">
document.createElement("header"); //自己创建header标签
</script>
  • IE6 下,块元素包含块元素浮动,如果被包含的块元素设置高度,则被包含的块元素会撑满一行,而不是随父元素浮动
    解决方案 : h2 {float: left;} //被包含的块元素也设置浮动,可解决此问题
  • 左右两个块元素,左面浮动,右面设置 margin-left,IE6 下会导致有一条缝隙的出现
    解决方案: .right { float: left;}
  • IE6 下子元素宽高大于父元素宽高,会撑开父元素
  • 关于 margin 的重叠 1.传递的 margin,对于现代浏览器可以触发 BFC,比如 overflow:hidden;对于 IE 低版本可以触发 haslayout,比如 zoom:1; 2.垂直方向上合并的 margin,我们尽量采用避开此布局方法的方式解决
  • IE6 下,display : inline-block;失效
  • IE6 最小高度
  • IE6 7 双边距问题
  • IE6 7 li 里元素都浮动会导致下方产生 4px 的间隙
    更多详见https://www.cnblogs.com/Lycheeling/p/5999407.html

4、文字单行居中,多行左对齐
详见https://blog.csdn.net/fungleo/article/details/49797311

  • 解决方法一:利用行内元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>文字测试</title>
<style>
/* 傻大本粗RESET*/
* {
margin: 0;
padding: 0;
list-style: none;
font-weight: normal;
font-style: normal;
}
body {
font-size: 13px;
font-family: tahoma, Helvetica, Arial, "\5FAE\8F6F\96C5\9ED1";
line-height: 1;
}
/* 代码开始 */
ul {
width: 500px;
margin: 100px auto;
overflow: hidden;
}
/* 开始了!!!! */
li {
/* 这些都不重要 */
float: left;
width: 100px;
background: #fafafa;
height: 50px;
margin-right: 10px;
/* 重点 */
text-align: center;
}
/* 重点 */
p {
display: inline-block;
text-align: left;
}
</style>
</head>
<body>
<ul>
<li><p>一行文字</p></li>
<li><p>这里是比较长的两行文字</p></li>
</ul>
</body>
</html>
  • 解决方法二:利用万能的表格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* 傻大本粗RESET*/
* {
margin: 0;
padding: 0;
list-style: none;
font-weight: normal;
font-style: normal;
}
body {
font-size: 13px;
font-family: tahoma, Helvetica, Arial, "\5FAE\8F6F\96C5\9ED1";
line-height: 1;
}
/* 代码开始 */
ul {
width: 500px;
margin: 100px auto;
overflow: hidden;
}
li {
loat: left;
width: 100px;
background: #fafafa;
height: 50px;
margin-right: 10px;
}
/* 重点 */
p {
display: table;
margin: 0 auto;
}
  • 利用图层遮盖解决的方法

5、多行文本显示省略号
6、1px 边框
7、doctype 不存在会发生什么
8、title 和 alt 区别
9、过渡效果

五、前后端协作及综合问题讲解

学会追根溯源的精神(要探索原理、多研究底层)
1、跨域
常见跨域方案有哪些?
线上代码跨域、本地开发跨域(代理)
allow-access-origin
jsonp(前后端都要改代码、不支持 post 请求、callback 函数名一定是变化的)
2、jsonp 原理

1
2
3
window.jsonp1;
function jsonp1() {}
//jsonp1({a:1,b:2})

3、http 与 https,运营商注入问题
https 更安全,公钥和私钥了解过吗?
http 的网站会出现广告,https 不会出现广告,为什么?
劫持注入问题:http 明文传输,运营商劫持注入广告内容,https 是密文传输
建议看【图解 http】
4、浏览器渲染机制,渲染引擎及 js 引擎
google v8 引擎——只包含了 js 引擎(如 nodejs 基于 v8 引擎)
回流和重绘——重绘不可避免,尽量避免回流(渲染引擎会做更多计算)
5、浏览器缓存机制
浏览器缓存优势和劣势:
[劣势]:如果修改代码后文件名不变,会导致用户不能及时加载最新的代码
[优势]:加载速度更快
contentHash 和 hash 在 webpack 中的区别是什么?
6、你在项目中遇到什么比较难的问题,怎么解决的(发散题)
多表达自己的特点和思路,多说说对待复杂问题的思路,不只是聊具体的问题和解决方法
7、你公司项目的开发流程是什么
评审阶段——排期阶段
确定接口——开发——前后端联调——测试——上线
线上验证
线上有 bug 怎么办?
赶紧恢复到上一个版本,保证系统正常运行
如果遇到数据库结构大变、程序大幅度变更的情况,赶紧修改线上 bug,重新上线
[测试是一个很重要的环节]
8、你对优雅编程有什么样的思考
代码设计想清楚(提高设计能力,多看开源项目源码)
好的代码(程序怎么写得漂亮)
面向对象编程
eslint 检测(使用 webpack 做强制约束)
9、如何思考扩展性和复用性之间的冲突
10、一门技术深入学习的思路
[英语一定要好]
先看官方文档,从头读到尾
看源代码(如何实现的)
看社区
11、框架的横向对比
angular(国内用得比较少)
vue(简单,国人用的多)
react(官方团队创新力比较强,社区更完善)

六、原生 JS、jQuery 常见问题讲解

1、面向对象编程和面向过程编程地区别
编程思路的问题
2、this 指向问题
3、普通函数与箭头函数
4、eval 函数是做什么的
可以直接执行 js 代码
在严格模式下,eval 的作用域是不同的
5、函数节流和函数防抖
6、作用域链
7、原型链继承的机制
8、垃圾回收(GC)的机制是什么
9、promise 精讲
10、数组方法
11、深拷贝
12、$(window).onload和$(window).ready 的区别 1.执行时间
​ window.onload 必须等到页面内包括图片的所有元素加载完毕后才能执行。
​ $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。
2.编写个数不同
​ window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个
​ $(document).ready()可以同时编写多个,并且都可以得到执行 3.简化写法
​ window.onload 没有简化写法
​ $(document).ready(function(){})可以简写成$(function(){});