东田数码科技前端面经
东田数码科技有限公司前端面经
一个月三次面试,也是逐渐积攒了许多经验,也有遇到面试官问到的重复的问题,也有一些我不懂的问题,以下是4.27东田前端面经,希望给大家做参考。
1-自我介绍
我是ac鸽,就读与XXX,巴拉巴拉。建议说一下自己熟悉的技术栈,还有对前端有浓厚的兴趣,让面试官有问题可问。
2-笔试
一来就让我先填一些基本信息,然后就先让我填一下笔试内容。内容如下,波珠还是有准备的,也是完成了80%多。
3-less/css实现水平垂直居中的div(两张方法以上)
这里波珠在上一次面试的时候已经被问过一次了,所以这道题也是毫无例外的拿下了。
/* 方法1:Flex布局 */
.container {display: flex;justify-content: center;align-items: center;height: 100vh;
}/* 方法2:Grid布局 */
.container {display: grid;place-items: center;height: 100vh;
}/* 方法3:绝对定位 + Transform */
.container {position: relative;height: 100vh;
}
.inner-box {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);
}/* 方法4:绝对定位 + margin auto */
.container {position: relative;height: 100vh;
}
.inner-box {position: absolute;top: 0;left: 0;right: 0;bottom: 0;margin: auto;width: fit-content;height: fit-content;
}
4. 移动端适配方案
这个波珠在面试的路上刚好刷到了,恰巧就拿下了嘻嘻。
-
rem方案(推荐):
- 通过JS动态设置
document.documentElement.style.fontSize
- 结合
postcss-pxtorem
自动转换px为rem - 基准值通常设置为设计稿宽度/10(如375px设计稿 → 37.5px)
- 通过JS动态设置
-
viewport方案(vw/vh):
/* 设计稿750px时,1vw = 7.5px */ .element {width: (100vw / 7.5); /* 100px → 13.333vw */ }
- 使用
postcss-px-to-viewport
插件自动转换
- 使用
-
媒体查询:
@media screen and (max-width: 375px) {.element { font-size: 14px; } }
-
Flexible方案(阿里方案):
- 通过JS检测dpr动态调整viewport和font-size
- 已逐步被vw方案取代
-
响应式图片:
<img src="small.jpg" srcset="medium.jpg 768w, large.jpg 1024w">
5. Vue中v-if和v-show的区别
优化后答案:
v-if | v-show | |
---|---|---|
编译方式 | 动态添加/移除DOM | 始终保留DOM,切换display属性 |
性能开销 | 较高的切换开销 | 较高的初始渲染开销 |
适用场景 | 运行时条件很少改变 | 需要频繁切换显示状态 |
生命周期 | 触发创建/销毁生命周期 | 不触发生命周期 |
使用建议:
- 需要权限控制/数据加载时用
v-if
- 选项卡切换等高频操作用
v-show
6. PC端与移动端事件对应关系
这个波珠没有准备,被宰了一道呜呜呜。只会个click,pc端还有对应的键盘事件。
PC端事件 | 移动端事件 | 特殊处理 |
---|---|---|
click | touchstart/touchend | 移动端有300ms延迟,可用fastclick 库解决 |
mouseover | touchmove | 需要阻止默认行为:e.preventDefault() |
mousedown | touchstart | 注意多点触控:通过e.touches 数组获取触点 |
mouseup | touchend | 注意触点离开时的坐标判断 |
mousemove | touchmove | 需要处理坐标计算:e.changedTouches[0].clientX |
dblclick | 无直接对应 | 可通过自定义手势识别实现 |
7. 防抖与节流
// 防抖:最后一次操作后执行
function debounce(fn, delay) {let timer = null;return function(...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
}// 节流:固定时间间隔执行
function throttle(fn, interval) {let lastTime = 0;return function(...args) {const now = Date.now();if (now - lastTime >= interval) {fn.apply(this, args);lastTime = now;}};
}
应用场景:
- 防抖:搜索框输入、窗口resize结束判断
- 节流:滚动加载、鼠标移动事件、游戏角色移动
- 回答计时器定时器差不多就OK了,但是也要会手写
8.前端三化深度解析(模块化/组件化/工程化)
一、模块化 (Modularization)
1.1 演进历程
// IIFE阶段(2015年前)
(function(window) {function fn1() {...}window.moduleA = { fn1 };
})(window);// CommonJS阶段(Node.js)
const moduleB = require('./moduleB');
module.exports = { ... };// ES Modules阶段(现代标准)
import moduleC from './moduleC.js';
export const func = () => {...};
1.2 核心价值
-
依赖管理:通过
import/require
明确定义依赖关系 -
作用域隔离:每个模块拥有独立词法作用域
-
按需加载:动态加载模块(Dynamic Import)
import('./module.js').then(module => {...});
1.3 进阶实践
-
Tree Shaking:通过静态分析消除死代码
-
循环引用:使用
import() + await
解决 -
模块联邦(Webpack 5):实现跨应用共享模块
// 模块提供方 new ModuleFederationPlugin({name: 'app1',exposes: { './Button': './src/Button' } })
二、组件化 (Componentization)
2.1 设计原则
原则 | 实现示例 |
---|---|
单一职责 | 按钮组件只处理点击交互 |
受控/非受控 | <Input value={value} onChange={...}/> |
组合优于继承 | 使用<Slot> 或children 进行组合 |
2.2 高级模式
// 高阶组件(HOC)
const withLogger = WrappedComponent => {return props => {useEffect(() => {console.log('Component mounted');}, []);return <WrappedComponent {...props} />;};
};// 渲染属性模式
<DataProvider render={data => (<Component data={data} />
)}/>
2.3 跨框架方案
<!-- Web Components -->
<template id="my-component"><style>...</style><div class="container"><slot name="content"></slot></div>
</template><script>customElements.define('my-component', class extends HTMLElement {constructor() {super();const template = document.getElementById('my-component');const shadowRoot = this.attachShadow({mode: 'open'});shadowRoot.appendChild(template.content.cloneNode(true));}});
</script>
三、工程化 (Engineering)
3.1 完整工具链
3.2 关键实践
-
自动化构建:
# 现代构建流程示例 npm run lint # 代码检查 npm run test:unit # 单元测试 npm run build # 生产构建 npm run deploy # 自动部署
-
微前端架构:
// 乾坤框架配置 registerMicroApps([{name: 'app1',entry: '//localhost:7100',container: '#container',activeRule: '/app1',} ]);
-
性能优化:
// 代码分割示例(React) const OtherComponent = React.lazy(() => import('./OtherComponent'));function MyComponent() {return (<Suspense fallback={<div>Loading...</div>}><OtherComponent /></Suspense>); }
四、三化协同关系
4.1 开发流程映射
4.2 项目演进示例
- 初创阶段:使用
create-react-app
快速搭建基础工程 - 成长阶段:
- 拆分业务模块为独立npm包
- 建立UI组件库
- 成熟阶段:
- 实现微前端架构
- 搭建私有镜像仓库
- 实施灰度发布策略
五、面试延伸问题准备
5.1 常见追问
-
“如何设计一个可维护的React组件?”
- 参考答案要素:
- PropTypes/TS类型定义
- 清晰的目录结构(index.js + style.module.css)
- 单元测试覆盖率要求
- 参考答案要素:
-
“Webpack和Vite的核心差异是什么?”
- 关键点对比:
Webpack Vite 构建机制 Bundle-based ESM-based 冷启动时间 较慢(全量打包) 极快(按需编译) 适用场景 复杂项目 现代浏览器项目
- 关键点对比:
-
“如何实现跨团队组件共享?”
- 解决方案:
- 搭建私有npm仓库(Verdaccio)
- 使用Storybook建设组件文档站
- 制定版本管理规范(Semver)
- 解决方案:
5.2 项目经验包装建议
-
模块化案例:
“在XX项目中,我将用户认证模块解耦为独立SDK,使多个子项目复用率提升70%” -
组件化案例:
“主导开发可视化图表组件库,通过参数化配置支持10+业务场景,减少重复代码量约3万行” -
工程化案例:
“引入GitLab CI流水线后,构建部署时间从15分钟缩短至2分钟,并实现自动化回归测试”
前端三化「说人话」总结:
1. 模块化 → 代码分块,像拼乐高
- 干啥用? 把代码拆成一个个独立小文件,避免所有代码堆一起
- 举个栗子🌰:
- 用户登录功能 → 单独写个
login.js
- 支付功能 → 单独写个
pay.js
- 用户登录功能 → 单独写个
- 好处:改一个功能不会影响其他,还能重复使用
2. 组件化 → 造可复用的零件
- 干啥用? 把界面拆成可复用的零件(按钮/表格/弹窗)
- 现实类比:就像手机零件,换个摄像头不影响屏幕
- 开发日常:
<!-- 直接复用别人写好的组件 --> <SearchBar @search="handleSearch"/> <DatePicker v-model="date"/>
- 好处:不用重复造轮子,团队协作更高效
3. 工程化 → 搞自动化生产线
- 核心目标:让开发→测试→上线像流水线一样自动运行
- 标配工具:
- 代码质检员:ESLint(检查代码格式错误)
- 自动打包机:Webpack(把代码压缩打包)
- 自动测试机:Jest(自动跑测试用例)
- 一键部署:CI/CD(代码提交后自动发布)
- 好处:减少人工操作,避免低级错误
三化关系一句话总结:
- 模块化:把代码写成独立积木块
- 组件化:把积木块拼成标准零件
- 工程化:建个自动化工厂批量生产
面试加分金句:
“我们项目用模块化解耦业务逻辑,通过组件库统一UI规范,最后用工程化工具实现从代码提交到自动部署的全流程——就像先造零件、再组装汽车、最后建自动化工厂”
通俗版理解检测✅
下次被问到时,试着用「拼乐高→造零件→建工厂」的比喻串起来讲,面试官听完绝对眼前一亮! ✨
面试
面试的时候面试官没问什么问题,他看了我简历发现我用的技术栈跟他们公司的业务比较契合,也是使用动画跟3D结合,问了我的项目都是一个人开发吗?是都上线了是吗?我说都是的,上面都有部署链接。
后面面试官问我要什么问题想问的,我就问了一些常见的问题。
1-公司的具体业务是?
2-有加班吗?加班有调休还是有加班费?
3-一周上几天班?
4-在贵公司能学到什么东西?
5-进了公司,是使用公司的电脑还是自带笔记本?(因为涉及到公司的保密,一般都是公司的电脑)
6-薪资大概能开到什么水平?由于波珠只是的憋佬仔实习生,也不敢要太多哈哈,反正希望越多越好。
祝大家都能拿到满意的offer!!