面试必备 Vue React Webpack 全掌握
Vue 基本使用
指令、插值
- 插值、表达式
- 指令、动态属性
- v-html 会有 xss 风险,会覆盖子组件
computed 和 watch
- computed 有缓存,data 不变则不会重新计算
- watch 如何深度监听
- watch 监听引用类型,拿不到 oldVal
1 | watch : { |
class style
- 使用动态属性
- 使用驼峰式写法
条件渲染
- v-if v-else 的用法,可以使用变量,也可以使用 === 表达式
- v-if 和 v-show 的区别
- v-if 和 v-show 的使用场景
循环列表的渲染
- 如何遍历对象——也可以使用 v-for
- key 的重要性,key 不能乱写,如 random 或者 index
- v-for 和 v-if 是不能一起使用的
事件
- event 参数,自定义参数($event,原生 event)
- 事件修饰符,按键修饰符
- 【观察】事件被绑定到哪里(写在哪,挂载在哪)
表单
- v-model
- 常见的表单项, textarea,checkbox,radio,select
- 修饰符 lazy number trim
vue 组件使用
- props 和 $emit
- 组件间通讯-自定义事件
- 组件生命周期
单个组件
- 挂载阶段
- 更新阶段
- 销毁阶段
created vue 实例化完成
mounted 元素挂载完成
父子组件
创建从外到内,渲染从内到外
Vue 高级特性
- 自定义 v-model
- $nextick
- slot
- 动态、异步组件
- keep-alive
- mixin
v-model
1 | <intput :value="text" @input="$emit('change', $event.target.value)" /> |
1 | export default { |
$nextTick
- Vue 是异步渲染
- data 改变之后,DOM 不会立刻渲染
- $nextTick 会在 DOM 渲染之后被触发,以获取最新的 DOM 节点
slot
- 基本使用
- 作用域插槽
- 具名插槽
动态组件
- :is=”component-name” 用法
<component :is="NextTick" />
- 需要根据数据,动态渲染的场景。即组件类型不确定
Vue 如何加载异步组件
- import() 函数
- 按需加载,异步加载大组件
keep-alive
- 缓存组件
- 频繁切换,不需要重复渲染
- Vue 常见的性能优化
mixins
- 多个组件有相同的逻辑,抽离出来
- mixin 并不是最完美的解决方案,会有一些问题
- Vue3 提出的 CompositionAPI 旨在解决这些问题
mixin 缺点
- 变量来源不明确,不利于阅读
- 多个 mixin 可能会造成命名冲突
- mixin 和组件可能会出现多对多的关系,复杂度高
Vuex 使用
基本概念
- state
- getters
- action
- mutation
用于 vue 组件
- dispatch
- commit
- mapState
- mapGetters
- mapActions
- mapMutations
VueRouter
- 路由模式,(hash,H5 history)
- 路由配置,(动态路由,懒加载)
Vue 原理
- 组件化
- 响应式
- vdom 和 diff
- 模板编译
- 渲染过程
- 前端路由
组件化基础
- “很久以前”就有组件化
- 数据驱动视图(MVVM,setState)
- 传统组件,只是静态渲染,更新还是要依赖于操作 DOM
- 数据驱动视图 - Vue MVVM
- 数据驱动视图 - React setState
Vue MVVM
Vue 响应式
- 核心 API Object.defineProperty
- proxy 有兼容性的问题,且无法 polyfill
- 监听对象,监听数组
- 复杂对象,深度监听
- 几个缺点
- Object.defineProperty 深度监听,需要递归到底,一次性计算量大
- 无法监听新增属性,删除属性
- 无法监听原生数组,需要做特殊处理
虚拟 DOM 和 diff
- vdom 是实现 vue 和 React 的重要基石
- diff 算法是 vdom 中最核心最关键的部分
- vdom 是一个热门话题,也是面试中最热门的话题
- DOM 的操作非常耗费性能
- 以前使用 jQuery,可以自行控制 DOM 操作的时机,手动调整
- Vue 和 React 是数据驱动视图,如何有效的控制 DOM 操作
- 有了一定复杂度,想减少计算次数比较难
- 能不能把计算,更多的转移为 JS 计算,因为 JS 执行速度很快
- vdom - 用 js 模拟 DOM 结构,计算出最小的变更,操作 DOM
- vue3 重写了 vdom 的代码,优化了性能
- 但是 vdom 的基本里边不变,面试考点也不变
snabbdom 使用
- 用 JS 模拟 DOM 结构(vnode)
- 新旧 vnode 对比,得出最小的更新范围,最后更新 DOM
- 数据驱动视图的模式下,有效控制 DOM 的操作
diff 算法
树 diff 的时间复杂度是 O(n^3)——算法不可用的
优化时间复杂度到 O(n)
- 只比较同一层级,不跨级比较
- tag 不相同,则直接删掉重建,不再深度比较
- tag 和 key, 两者都相同,则认为是相同节点,不在深度比较
h 函数: 返回一个 vnode
- patchNode
- addVnodes removeVNodes
- updateChildren
- 细节不重要,updateChildren 的过程也不重要,不要深究
- vdom 的核心概念很重要,h,vnode,patch、diff、key
- vdom 存在的价值更加重要:数据驱动视图,控制 DOM 操作
模板编译
- 模板是 vue 开发中最常用的部分,即与使用相关联的原理
- 他不是 html,有指令、插值、JS 表达式到底是什么
- 面试不会直接问,但是会通过“组件渲染和更新过程”考察
- v-if 三元表达式
- v-for _l renderList
- 事件
- v-model
vue-template-compiler
组件 渲染/更新 过程
- 响应式:监听 data 属性的 getter 和 setter (包括数组)
- 模板编译:模板到 render 函数,再到 vnode
- vdom :patch(ele, vnode) patch(vnode, newVNode)
初次渲染的过程
- 解析模板为 render 函数,(或者在开发环境中已经完成,vue-loader)
- 触发响应式,监听 data 属性 getter setter
- 执行 render 函数,生成 vnode,patch(ele, vnode)
更新过程
- 修改 data, 触发 setter(此前在 getter 中已被监听)
- 重新执行 render 函数,生成 newVNode
- patch(vnode, newVnode)
异步渲染
- 回顾$nexttick
- 汇总 data 的修改,一次性更新视图
- 减少 DOM 的操作次数,提高性能
前端路由的原理
路由模式
- hash
- history
hash 的特点
- hash 变化会触发网页的跳转,即浏览器的前进后退
- hash 变化不会刷新页面,SPA 必备特点
- hash 永远不会提交到 server 端
window.onhashchange = () => {}
H5 history
- 用 url 规范的路由,但跳转时不刷新页面
- history.pushState
- window.onpopstate
- 需要后端配合
Vue 面试真题
v-show v-if 区别
为何在 v-for 中使用 key
- 必须用 key,且不能是 index 和 random
- diff 算法中通过 tag 和 key 来判断,是否是 sameNode
- 减少渲染次数提升渲染性能
描述 Vue 组件的生命周期
- 单组件的生命周期图
- 父子组件生命周期关系
Vue 组件如何通讯
- 父子组件 props 和 this.$emit
- 自定义事件,event.$on event.$off event.$emit
- vuex
描述组件渲染和更新的过程
双向数据绑定 v-model 的实现原理
- ipnut 元素的 value = this.name
- 绑定 input 事件 this.name = $event.target.value
- data 更新触发 re-render
对 mvvm 的理解
computed 有何特点
- 缓存,data 不变不会重新计算
- 提高性能
为何组件 data 必须是一个函数
ajax 请求应该放在那个生命周期中
- mounted
- js 是单线程的,ajax 异步获取数据
- 放在 mounted 之前没有用只会让逻辑更加复杂
如何将组件所有 props 传递给子组件
- v-bind=”$props”
如何自己实现一个 v-model
多个组件有相同的逻辑,怎么抽离
mixin
何时要使用 异步组件
- 加载大组件
- 路由
何时需要使用 keep-alive
- 缓存组件,不需要重复渲染
- 性能优化
何时需要使用 beforeDestory
- 解绑自定义事件 event.$off
- 清除定时器
- 解绑自定义的 DOM 事件
什么是作用域插槽
Vuex 中 action 和 mutation 有什么区别
vue-router 常用的路由模式
vue-router 异步加载
请用 vnode 描述一个 DOM 结构
监听 data 变化的核心 API 是什么
Vue 如何监听数组变化
请描述响应式原理
Diff 算法的时间复杂度
简述 diff 算法的过程
Vue 为何是异步渲染,$nextTick 何用
Vue 性能优化
- 合理使用 v-show 和 v-if
- 合理使用 computed
- v-for 时加 key ,避免和 v-if 同时使用
- 自定义事件,以及 DOM 事件要及时销毁
- 合理使用 异步组件
- 合理使用 keep-alive
- data 层级不要太深
- 使用 vue-loader 在开发环境做模板预编译
- webpack 层的优化
- 前端通用的优化,图片懒加载
- 使用 SSR
Vue3
Vue3 对 Vue2 有什么优势
- 性能更小
- 体积更小
- 更好的 TS 开发的
- 更好的代码组织
- 更好的逻辑抽离
Composition API 和 Options API
- 不建议共用,会引起混乱
- 小型项目业务逻辑简单,用 Options API
- 中大型项目、复杂逻辑,用 Composition API
ref
- 生成值类型的响应式数据
- 可用于模板和 reactive
- 通过 .value 修改值
toRef
- 针对一个响应式对象(reactive 封装)的 prop
- 创建一个 ref,具有响应式
- 两者保持引用关系
toRefs
- 将响应式对象(reactive 封装)转换为普通对象
- 对象的每一个 prop 都是对应的 ref
- 两者保持引用关系
toRef 和 toRefs 的最佳使用方式
- 用 reactive 做对象的响应式,用 ref 做值类型的响应式
- setup 中返回 toRefs(state) 或者 toRef(state, ‘xxx’)
- ref 的变量命名都用 xxxRef
- 合成函数返回响应式对象时,使用 toRefs
深入理解 ref
为什么使用 ref
- 返回值类型,会丢失响应式
- 如 setup, computed,合成函数,都有可能返回值类型
- Vue 如不定义 ref,用户会自造 ref,反而混乱
为什么需要.value
- ref 是一个对象(不丢失响应式),value 存储值
- 通过 .value 属性的 get 和 set 实现响应式
- 用于模板、reactive 时,不需要.value,其他情况下都需要
为什么需要 toRef 和 toRefs
初衷:不丢失响应式的情况下,把数据对象 分解/扩散
前提:针对的是响应式对象(reactive 封装的)非普通对象
注意:不创造响应式,而是延续响应式
vue 升级了哪些重要的功能
- createApp
- emit 属性
- 生命周期
- 多事件
- Fragment
- 移除 .sync
- 异步组件的写法
- 移除 filter
- suspense
- composition API
Vue2 如何实现响应式
Object.defineProperty 的缺点
- 深度监听需要一次性递归
- 无法监听新增属性和删除属性
- 无法监听数组,需要特殊处理
Reflect 作用
- 和 Proxyu 能力一一对应
- 规范化、标准化、函数式
- 代替 object 的工具函数
Proxy 实现响应式
- 深度监听,性能更好
- 可监听 新增、删除属性
- 可监听数组变化
watch 和 watchEffect 区别
- 两者都可以监听 data 属性变化
- watch 需要明确监听哪个属性
- watchEffect 会根据其中的属性,自动监听其变化
setup 中如何获取组件的实例
- 在 setup 和其他 compositionAPI 中没有 this
- 可以通过 getCurrentInstance 获取当前实例
- 若使用 options API 可照常使用 this
Vue3 为何比 Vue2 快
- Proxy 响应式
- PatchFlag
- hoistStatic
- cacheHandler
- SSR 优化
- tree-shaking
PatchFlag
- 编译模板时,动态节点做标记
- 标记,分为不同类型,如 TEXT,PROPS
- diff 算法时,可以区分静态节点,以及不同类型的动态节点
hoistStatic
- 将静态节点的定义,提升到父作用域,缓存起来
- 多个相邻的静态节点会被合并起来
- 典型的那空间换时间的优化策略
cacheHandler
- 缓存事件
SSR 优化
- 静态节点直接输出,绕过了 vdom
- 动态节点,还是需要动态渲染
vite 是什么
- 一个前端的打包工具,Vue 作者发起的项目
- 借助 Vue 的影响力,发展较快,和 webpack 竞争
- 优势: 开发环境下无需打包,启动快
Vite 为何启动快
- 开发环境使用 ES Module,无需打包——非常快
- 生产环境下使用 rollup,并不会快很多
es module: type=’module’
Composition API 和 react hooks 对比
- 前者 setup 只会调用一次,而后者函数会被调用很多次
- 前者无需调用 useMemo,useCallback 因为 setup 只会调用一次
- 前者无需顾虑调用的顺序,而后者需要保证 hooks 的顺序一致
- 前者 reactive 和 ref 比后者 useState,要更加难以理解
Vue3 和 JSX
jsx 和 template 区别
语法上是有很大的区别的
本质是相同的
具体示例,插值,自定义组件,属性和事件,条件和循环
jsx 的本质就是 js 代码,可以使用 js 的任何能力
template 只能嵌入简单的 js 表达式,其他需要指令,如 v-if
jsx 已经成为 es 规范,template 还是 Vue 自家的规范
Vue3 script setup
React
关于 react 17
- 没有明显的新特性,使用是和 react 16 是一致的
- 面试时也不会被重点考察
React 基本使用
事件
- bind this
- 关于 event 参数
- 传递自定义参数
react 中的 event 不是原生的 event ,而是 syntheticEvent(组合事件)
react 事件和 DOM 事件的区别
- event 是 SyntheticEvent ,模拟出原生事件所有的能力
- event.nativeEvent 是原生事件对象
- 多有的时间都被挂载到 document 上
- 和 DOM 时间不一样,和 Vue 事件也不一样
React 16 绑定到 document 上
react 17 绑定在 root 组件上
有利于多个 react 版本并存,例如微前端
表单
- 受控组件
- input textarea select 用 value
- checkbox radio 用 checked
setState
- 不可变值
- 可能是异步更新
- 可能会被合并
setState 是同步还是异步的
- 正常情况下是异步的
- setTimeout 中 setState 是同步的
- 自定义 DOM 事件中也是同步的
setState 可能会被合并
- 传入对象会被合并
- 传入函数不会被合并
单组件生命周期
React 高级特性
- 函数组件
- 非受控组件
- Portals
- context
- 异步组件
- 性能优化
- 高阶组件 HOC
- Render Props
函数组件
- 输入 props 输出 jsx
- 没有实例,没有生命周期,没有 state
- 不能扩展其他方法
什么是非受控组件
- ref
- defaultValue defaultChecked
- 手动操作 DOM 元素
使用场景
- 必须手动操作 DOM 元素,setState 实现不了
- 文件上传,input type=’file’
- 某些富文本编辑器,需要传入 DOM 元素
受控组件 vs 非受控组件
- 优先使用受控组件,符合 React 设计原则
- 必须操作 DOM 时,再使用非受控组件
Portals
- 组件默认会按照既定的层级嵌套渲染
- 如何让组件渲染到父组件外
ReactDOM.createPortals
context
- 公共信息(语言,主题)如何传递给每个组件
- 用 props 太繁琐
- 用 redux 小题大做
react 如何加载异步组件
性能优化
- shouldComponentUpdate
- PureComponent 和 React.memo
- 不可变值 immutable.js
React 默认:父组件更新,子组件则默认无条件更新
性能优化对于 React 更加重要!
SCU 一定每次都要用吗——需要的时候才会优化
shouldComponentUpdate 在做深层比较的时候,如果使用 isEqual 会对数组或者对象做深层比较,(一次性递归到底)
- SCU 默认返回 true,即 React 默认重新渲染所有子组件
- 必须配合不可变值一起使用
- 可先不使用 shouldComponentUpdate ,有性能问题时在考虑使用
PureComponent 和 memo
- PureComponent,scu 中实现了浅比较
- React.memo. 函数组件中的 PureComponent
- 浅比较已经适用大部分情况(尽量不要做深度比较)
immutable.js
- 彻底拥抱“不可变值”
- 基于共享数据(不是深拷贝),速度好
- 有一定学习和迁移成本,按需使用
关于组件公共逻辑的抽离
- mixin 已经被 React 废弃
- 高阶组件 HOC
- render props
高阶组件不是一种功能,而是一种模式
- 透传所有 props(Vue 中 v-bind $props)
- 增加 mouse 属性
redux connect 是高阶组件
向组件属性中传入 render 函数
Redux 使用
- 基本概念
- 单向数据流
- react-redux
- 异步 action
- 中间件
基本概念
- store state
- action
- reducer
流程
- dispatch(action)
- reducer -> newState
- subscribe 触发通知
react-redux
- connect
- mapStateToProps mapDispatchToProps
- redux-thunk
- redux-promise
- redux-saga
react router
- 路由模式(hash ,H5 history)
- 路由配置(动态路由,懒加载)
- 掌握基本使用
React 原理
- 大厂使用 React 概率更高
- react 对开发人员要求更高
- 大厂更偏爱考察原理
- 函数式编程
- vdom 和 diff 算法
- JSX 的本质
- 合成事件
- setState batchUpdate
- 组件渲染过程
函数式编程
- 一种编程范式,概念比较多
- 纯函数
- 不可变值
vdom 和 diff
- h 函数
- 返回 vnode 数据结构
- patch 函数
diff 算法的改造
- 只比较同一层级,不跨级比较
- tag 相同,则之间删掉重建,不再深度比较
- tag 和 key ,两者都相同,则认为是相同节点,不在深度比较
- Vue2 Vue3 React 三者实现 vdom 细节均不相同
- 核心概念和实现思路都一样
- 面试主要考察后者,不用全部掌握细节
JSX 的本质
- JSX 等同于 Vue 的模板
- Vue 模板不是 HTML
- JSX 也不是 JS
- React.createElement 即 h 函数,返回 vnode
- 第一个参数,可能是组件,也可能是 html tag
- 组件名,首字母必须大写(React 规定)
react 合成事件机制
为什么要合成事件机制
- 更好的兼容性和跨平台
- 挂载到 document 上,减少内存消耗,避免频繁解绑
- 方便事件的统一管理
React 的 batchUpdate 机制
- 有的时候是异步的(普通使用),有时同步(setTimeout,DOM 事件)
- 有时合并(对象形式),有时不合并(函数形式)
- 后者比较好理解,向 Object.assign ,主要讲解后者
- setState 主流程
- batchUpdate 机制
- transaction (事物)机制
- setState 无所谓异步还是同步
- 看是否可以命中 batchUpdate 机制
- 判断 isBatchingUpdates
那些可以命中 batchUpdate 机制
- 生命周期(和它调用的函数)
- React 中注册的时间(和它调用的函数)
- React 可以“管理”的入口
- setTimeout setInterval 等(和它调用的函数)
- 自定义的 DOM 事件(和它调用的函数)
- React “管不到”的入口
简述 transaction 事务机制
组件渲染和更新过程
- JSX 如何渲染为页面
- setState 之后如何更新页面
- 面试考察全流程
- props state
- render() 生成 vnode
- patch(elem, vnode)
- setState(newState) –> dirtyComponents(可能有子组件)
- render() 生成 newVnode
- patch(vnode, newVnode)
更新的两个阶段
- 上述 patch 被拆分成了两个阶段
- reconciliation 阶段 - 执行 diff 算法,纯 JS 计算
- commit 阶段 - 将 diff 结果渲染 DOM
如果不拆分成两个阶段,可能会有性能问题
- js 是单线程,且和 DOM 渲染公用一个线程
- 当组件足够复杂,组件更新时计算和渲染都压力大
- 同时再有 DOM 操作需求,(动画,鼠标拖拽),将卡顿
解决方案 fiber
- 将 reconciliation 阶段进行任务拆分,(commit 无法拆分)
- DOM 需要渲染时暂停,空闲时恢复
- window.requestIdleCallback
React 面试真题
组件间如何通讯
JSX 的本质是什么
context 是什么如何应用
shouldComponentUpdate 的用途
redux 单向数据流
setState 场景题
什么是纯函数
React 组件证明周期(单组件,父子组件)
ajax 应该在那个生命周期上
渲染列表,为何使用 key
函数组件和 class 组件的区别
什么是受控组件
何时使用异步组件
多个组件有公共逻辑,如何抽离
redux 如何进行异步请求
react-router 如何配置懒加载
PureComponent 有何区别
React 事件和 DOM 事件的区别
React 性能优化
- 渲染列表时使用 key
- 自定义事件 DOM 事件及时销毁
- 合理使用异步组件
- 减少函数 bind this 的次数
- 合理使用 shouldComponentUpdate PureComponent 和 memo
- 合理使用 Immuta.js
- webpack 层面的优化
- 前端通用的性能优化,如图片懒加载
- 使用 SSR
React 和 Vue 的区别
共同点
- 都支持组件化
- 都是数据驱动视图
- 都使用 vdom 操作 DOM
不同点
- React 使用 jsx 拥抱 js ,vue 使用模板拥抱 html
- React 函数式编程,Vue 声明式编程
- React 更多的需要自力更生,Vue 把想要的都给你
Webpack
- webpack 已经是前端打包构建的不二选择
- 每日必用,面试必考
- 成熟的工具,重点在于配置和使用,原理并不高优
webpack 5
- webpack 5 主要是内部效率的优化
- 对于 webpack4 ,没有太多使用上的改动
- 你可以直接使用 webpack5
webpack 基本配置
- 拆分配置 和 merge
- 启动本地服务
- 处理 es6
- 处理样式
- 处理图片
- (模块化)
postcss 兼容性处理
webpack 高级配置
- 多入口
- 抽离 css 文件
- 抽离公共代码
- 懒加载
- 处理 jsx 处理 vue
module chunk bundle 的区别
- module - 各个源码文件,webpack 中一切皆模块
- chunk - 多模块合成的 如 entry import() splitChunk
- bundle - 最终输出的文件
webpack 性能优化
webpack 怎么优化打包构建速度,开发体验和效率
优化产出代码 - 产品性能
优化 babel-loader
ignorePlugin 避免引用无用模块
noParse 避免重复打包
ignorePlugin vs noParse
- IgnorePlugin 直接不引入,代码中没有
- noParse 引入,但不打包
happyPack 多进程打包
- JS 单线程,开启多进程打包
- 提高构建速度,特别是多核 CPU
parallelUglifyPlugin 多进程压缩 JS
- webpack 内置 uglify 工具压缩 JS
- JS 单线程,开启多进程压缩更快
- 和 happyPack 同理
关于开启多线程
- 项目较大,打包较慢,开启多线程能提升速度
- 项目较小,打包较快,开启多进程会降低速度
- 按需使用
自动刷新
热更新
- 自动刷新:整个网页全部刷新,速度较慢
- 自动刷新网页的状态会丢失
- 热更新就是新代码生效,网页不刷新,状态不丢失
dllPlugin 动态链接库插件
- 前端框架如 vue react 体积大,构建慢
- 较稳定,不常更新版本
- 同一个版本只构建一次即可,不用每次都重新构建
- webpack 已经内置了 DllPlugin 支持
- DllPlugin - 打包出 dll 文件
- DllReferencePlugin - 使用 dll 文件
1 | const path = require("path"); |
webpack 优化构建速度(可以用于生产环境)
- 优化 babel-loader include exclude
- IgnorePlugins
- noParse
- happyPack
- ParallelUglifyPlugin
webpack 优化构建速度(不可用于生产环境)
- 自动刷新
- 热更新
- DllPlugin
webpack 性能优化 - 产出代码
- 体积更小
- 合理分包,不重复加载
- 速度更快,内存使用更小
- 小图片 base64 编码
- bundle 加 hash
- 懒加载
- 提取公共代码
- IgnorePlugin
- 使用 CDN 加速
- 使用 production
- Scope Hosting
使用 Production
- 开启代码压缩
- vue react 等会删掉调试代码(如开发环境下的 warning)
- 启用 tree shaking
必须使用 ES6 Module 才能让 tree-shaking 生效
commonjs 就不行
ES Module 和 Commonjs 的区别
- ES module 静态引入,编译时引入
- commonjs 动态引入,执行时引入
- 只有 ES6 Module 才能静态分析,实现 Tree-shaking
Scope Hosting
- 代码体积会更小
- 创建函数作用域更少
- 代码的可读性更好
babel
- 环境搭建
- .babelrc 配置
- preset 和 plugins
preset 是 plugins 的集合
什么是 babel-polyfill
- 什么是 polyfill
- core-js 和 regenerator
- babel-polyfill 就是上面两者的集合
- babel-polyfill 在 babel 7.4 之后被弃用
- 推荐直接使用 core-js 和 regenerator
core-js: polyfill 集合
babel-polyfill 如何按需引入
- 文件较大
- 只有一部分功能,无需全部引入
- 配置按需引入
1 | { |
问题
- 污染了全局环境
- 如果做一个 web 系统,则无碍
- 如果是一个第三方的 lib,会有问题
babel-runtime
Webpack 面试题
前端为什么要进行打包构建
- 体积更小(tree-shaking、压缩、合并),加载更快
- 编译高级语言或语法(TS,ES6+,模块化,scss)
- 兼容性和错误检查(Polyfill,postcss,eslint)
- 统一高校的开发环境
- 统一的构建流程和产出标准
- 继承公司构建规范(提测、上线)
module chunk bundle 的区别
loader 和 plugins 的区别
常见 loader 和 plugins
babel 和 webpack 的区别
如何产出一个 lib
babel-polyfill 和 babel-runtime 的区别
webpack 如何实现懒加载
为何 Proxy 不能被 polyfill
webpack 优化构建速度
webpack 优化产出代码
组件设计
- 从功能上拆分层次
- 尽量让组件原子化
- 容器组件(只管理数据) UI 组件(只显示视图)
React Hooks
- 可选功能
- 100% 向后兼容,没有破坏性改动
- 不会取代 class 组件,尚无计划要移除 class 组件
函数组件的特点
- 没有组件实例
- 没有生命周期
- 没有 state 和 setState,只能接受 props
class 组件的问题
- 大型组件很难拆分和重构,很难测试(即 class 不易拆分)
- 相同业务逻辑,分散到各个方法中逻辑混乱
- 复用逻辑复杂,Mixins,HOC,Render Props
react 组件更易用函数表达
- react 倡导函数式编程
- 函数更灵活更易拆分,更易测试
- 但函数组件太简单,需要增强能力——hooks
state hook
- 默认组件没有 state
- 函数组件是一个纯函数,执行完就销毁,无法储存 state
- 需要 state hook ,即把 state 功能“钩”到纯函数中
Effect
- didMount didUpdate - useEffect
- didMount - useEffect(()=>{},[])
模拟 unmount 的时候注意事项
其他 hooks
- useRef
- useContext
- usereducer
- useMemo
- useCallback
自定义 hooks
- 封装通用的功能
- 开发和使用第三方 hooks
- 自定义 hook 带来无线的扩展性,解耦代码
Hooks 使用规范
- 只能用于 react 组件和自定义 hook 中,其他地方不可以
- 只能用于顶层代码,不能用于循环判断中使用 hooks
- eslint 插件 eslint-plugin-react-hooks
为何 Hooks 要依赖于调用顺序
- 函数组件,纯函数,执行完即销毁
- 所以,无论组件初始化,还是组件更新
- 都会执行过一次这个函数,获取最新的组件
- render: 初始化 state 的值 “张三”
- re-render:读取 state 的值 “张三”
- render: 添加 effect 函数
- re-render:替换 effect 函数,内部的函数也会重新定义
class 组件逻辑复用
- mixin 早已废弃
- 高阶组件 HOC
- render props
mixin 问题
- 变量作用域来源不清楚
- 属性重名
- mixin 引入过多会导致顺序冲突
HOC
- 组件层级嵌套过多,不易渲染,不一调试
- HOC 会劫持 props,必须严格遵守规范,容易出现疏漏
render props
- 学习成本较高,不易理解
- 只能传递纯函数,默认情况下纯函数功能有限
Hooks 组件逻辑复用有什么好处
- 完全符合 Hooks 原有规则,没有其他要求,易理解记忆
- 变量作用域很明确
- 不会产生组件嵌套
React Hooks 注意事项
- useState 初始化值,只有第一次有效
- useEffect 不能修改 state
- useEffect 可能出现死循环