前端面试总结

vue

v-show 和 v-if 的区别

  1. v-show 通过 css display 控制显示和隐藏
  2. v-if 组件真正的渲染和销毁, 而不是显示和隐藏
  3. 频繁切换显示状态用 v-show, 否则用 v-if

为何在 v-for 中用 key

  1. 必须用 key, 且不能是 index 和 random
  2. diff 算法中通过 tag 和 key 来判断, 是否是 sameNode
  3. 减少渲染次次数, 提升渲染性能

描述 vue 组件生命周期(父子组件)

  1. 单组件生命周期图
  2. 父子组件生命周期关系

vue 组件如何通讯(常见)

  1. 父子组件 props 和 this.$emit
  2. 自定义事件 event.$on event.$off event.$emit
  3. vuex

描述组件渲染和更新的过程

Alt text

双向数据绑定 v-model 的实现原理

  1. input 元素的 value = this.name
  2. 绑定 input 事件 this.name = $event.target.value
  3. data 更新触发 re-render

对 MVVM 的理解

Alt text

computed 有何特点

  1. 有缓存, data 不变不会重新计算
  2. 提高性能

为何组件中的 data 必须是一个函数

组件是可复用的 vue 实例, 如果组件被复用, data 又不是函数, data 会指向同一个对象, 会相互影响.

ajax 请求应该放在哪个生命周期

  1. mounted
  2. js 是单线程的, ajax 异步获取数据
  3. 放在 mounted 之前没有用, 只会让逻辑更加混乱

在created的时候,视图中的dom并没有被渲染出来,所以此时如果直接去操作dom节点,无法找到相关元素。
在mounted中,由于此时的dom元素已经渲染出来了,所以可以直接使用dom节点。
一般情况下,都放在mounted中,保证逻辑的统一性。因为生命周期是同步执行的,ajax是异步执行的。
服务端渲染不支持mounted方法,所以在服务端渲染的情况下统一放在created中。

如何将组件所有 props 传递给子组件?

  1. v-bind=”$props”

如何自己实现 v-model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,也可以自定义, 受用 model 选项就可以了

多个组件有相同的逻辑, 如何抽离?

  • mixin
  • 以及 mixin 的一些缺点

何时使用异步组件

  1. 加载大组件
  2. 路由异步加载

何时需要使用 keep-alive

  1. 可以缓存组件, 不需要重新渲染
  2. 如多个静态 tab 页的切换
  3. 优化性能

何时需要使用 beforeDestory

  1. 解绑自定义事件 event.$off
  2. 清除定时器
  3. 解绑自定义的 DOM 事件, 如 window scroll 等

什么是作用域插槽

vuex 中 action 和 mutation 有何区别

  1. action 中处理异步, mutation 不可以
  2. mutation 做原子操作
  3. action 可以整合多个mutation

vue-router 常用的路由模式

  1. hash 默认
  2. H5 history(需要服务端支持)
  3. 两者比较

如何配置 vue-router 异步加载

使用 import() 函数

请用 vnode 描述一个 dom 结构

监听 data 变化的核心 api 是什么

  1. Object.defineProperty
  2. 以及监听深度, 监听数组
  3. 有何缺点

vue 如何监听数组变化

  1. Object.defineProperty 不能监听数组变化
  2. 重新定义原型, 重写 push pop 等方法, 实现监听
  3. Proxy 可以原生监听数组变化

请描述响应式原理

  1. 监听 data 变化
  2. 组件渲染和更新的流程

diff 算法的时间复杂度

  1. O(n)
  2. 在 O(n^3) 基础上做了一些调整

简述 diff 算法过程

  1. patch(elem, vnode) 和 patch(vnode, newVnode)
  2. patchVnode 和 addVnodes 和 remvoeVnodes
  3. updateChildren(key 的重要性)

vue 为何是异步渲染, $nextTick 何用?

  1. 异步渲染(以及合并 data 修改), 以提高渲染性能
  2. $nextTick 在 dom 更新完后, 触发回调

vue 常见性能优化方式

  1. 合理使用 v-show 和 v-if
  2. 合理使用 computed
  3. v-for 时加 key, 以及避免和 v-if 同时使用
  4. 自定义事件, dom 事件及时销毁
  5. 合理使用异步组件
  6. 合理使用 keep-alive
  7. data 层级不要太深
  8. 使用 vue-loader 在开发环境做模板编译(预编译)
  9. webpack 层面的优化
  10. 前端通用性能优化, 如懒加载
  11. 使用 SSR

webpack

webpack 常见配置

  1. 拆分配置和 merge
  2. 启动本地服务
  3. 处理 es6
  4. 处理样式
  5. 处理图片
  6. (模块化)

前端为何要进行打包和构建

  1. 体积更小(Tree-Shaking, 压缩, 合并), 加载更换
  2. 编译高级语言或者预发(TS, ES6+, 模块化, scss)
  3. 兼容性和错误检测(Polyfill, postcss, eslint)
  4. 统一, 高效的开发环境
  5. 统一的构建流程和产出标准
  6. 集成公司规范构建(提测, 上线等)

module chunk bundle 的区别

  1. module - 各个源码文件, webpack 中一切皆模块
  2. chunk - 多模块合并成的, 如 entry import() splitChunk
  3. bundle - 最终输出文件

loader 和 plugin 的区别

  1. loader 模块转换器, 如 less -> css
  2. plugin 扩展插件, 如 HtmlWebpackPlugin

Loader直译为”加载器”。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
Plugin直译为”插件”。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。

常见的 loader 和 plugin 有哪些

查看文档, 结合自己的项目说

loader
处理图片的 url-loader

转换编译
babel-loader 加载 ES2015+ 代码,然后使用 Babel 转译为 ES5

处理样式的
style-loader 将模块的导出作为样式添加到 DOM 中
css-loader 解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码
less-loader 加载和转译 LESS 文件
sass-loader 加载和转译 SASS/SCSS 文件
postcss-loader 使用 PostCSS 加载和转译 CSS/SSS 文件
stylus-loader 加载和转译 Stylus 文件

清理和测试
eslint-loader PreLoader,使用 ESLint 清理代码

框架
vue-loader 加载和转译 Vue 组件

plugin
CopyWebpackPlugin
将单个文件或整个目录复制到构建目录
DefinePlugin
允许在编译时(compile time)配置的全局常量

DllPlugin
为了极大减少构建时间,进行分离打包
EnvironmentPlugin
DefinePlugin 中 process.env 键的简写方式。
ExtractTextWebpackPlugin
从 bundle 中提取文本(CSS)到单独的文件
HotModuleReplacementPlugin
启用模块热替换(Enable Hot Module Replacement - HMR)
HtmlWebpackPlugin
简单创建 HTML 文件,用于服务器访问
I18nWebpackPlugin
为 bundle 增加国际化支持
IgnorePlugin
从 bundle 中排除某些模块

babel 和 webpack 的区别

  1. babel - js 新语法编译工具, 不关心模块化
  2. webpack - 打包构建工具, 是多个 loader plugin 的集合

如何产出一个 lib

  1. 参考 webpack.dll.js
  2. output.library

babel-polyfill 和 babel-runtime 的区别

  1. babel-polyfill 会污染全局
  2. babel-runtime 不会污染全局
  3. 产出第三方 lib 要用 babel-runtime

webpack 如何实现懒加载

  1. import()
  2. 结合 Vue react 异步组件
  3. 结合 VUe-router React-router 异步加载路由

为何 Proxy 不能被 Polyfill

  1. 如 Class 可以用 function 模拟
  2. 如 Promise 可以用 callback 模拟
  3. 但 Proxy 的功能用 Object.defineProperty 无法模拟

webpack 性能优化-构建速度

  1. 优化 babel-loader
  2. IgnorePlugin
  3. noParse
  4. happyPack
  5. ParallelUglifyPlugin
  6. 自动刷新
  7. 热更新
  8. DllPlugin

webpack 优化产出代码

  1. 小图片 base64 编码
  2. bundle 加 hash
  3. 懒加载
  4. 提取公共代码
  5. 使用 CDN 加速
  6. IgnorePlugin
  7. 使用 production
  8. Scope Hosting