一、webpack
1.1 什么是HappyPack
- JS 单线程,开启多进程打包
- 提高构建速度(特别是多核CPU)
使用 happyPack 多进程打包
const HappyPack = require('happypack')
// 步骤1 module.rules下-将对.js的文件交给id为label的HappyPack实例
{
test: /\.js$/,
use: ['happypack/loader?id=babel']
}
// 步骤2 happyPack开启多进程打包
new HappyPack({
// 用唯一的标识符 id 来代表当前的HappyPack 是用来处理一类特定的文件
id: 'babel',
// 如何处理.js 文件,用法和Loader 配置一样
loaders: ['babel-loader?cacheDirectory']
})
1.2 ParallelUglifyPlugin 多进程压缩JS
- webpack 内置 Uglify 工具压缩JS
- JS单线程,开启多进程压缩更快
- 和happyPack 同理
// 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码
const ParallelUglifyPlugin = require('ParallelUglifyPlugin')
new ParallelUglifyPlugin({
// 传递给 UglifyJS 的参数
// (还是使用 UglifyJS 压缩,只不过帮助开启了多进程)
uglifyJS: {
output: {
beautify: false, // 最紧凑的输出
comments: false // 删除所有的注释
},
compress: {
// 删除所有的 `console` 语句,可以兼容ie浏览器
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars: true
}
}
})
关于开启多进程
- 项目较大,打包较慢,开启多进程能提高速度
- 项目较小,打包很快,开发多进程会降低速度(进程开销)
1.3 webpack如何配置热更新
- 自动刷新:整个网页都刷新,速度较慢
- 自动刷新:状态会丢失(表单内数据会丢失)
- 热更新:新代码生效,网页不刷新,状态不丢失
HotModuleReplacementPlugin插件在webpack/lib下
// 配置 在entry中的index中
index: [
'webpack-dev-server/client?http://localhost:8080/',
'webpack/hot/dev-server',
path.join(srcPath, 'index.js')
]
// 配置2
在plugins中new HotModuleReplacementPlugin()
// 配置3
在devServer加hot: true
// 配置4
业务中加module.hot来确定哪些范围需要触发热更新
二、 React
2.1 函数组件和 class 组件的区别
函数组件:
- 纯函数,输入props,输出JSX;
- 没有实例,没有生命周期,没有state;
- 不能扩展其它方法;
2.2 什么是React非受控组件
2.2.1 非受控组件
- ref
- defaultValue defaultChecked
- 手动操作DOM 元素
2.2.2 受控组件 vs 非受控组件:
- 优先使用受控组件,符合React设计原则(数据驱动视图);
- 必须操作DOM时,再使用非受控组件;
2.2.3 非受控组件-使用场景:
- 必须手动操作DOM元素,setState实现不了;
- 文件上传
<input type=file>(setState只能实现和前端显示渲染相关的,文件上传这种交互的是实现不了的) - 某些富文本编辑器,需要传入DOM元素;
2.3 什么场景需要用React Portals
2.3.1 Portals:
- 组件默认会按照既定层次嵌套渲染;
- 如何让组件渲染到父组件以外?
定位为fixed的元素,有些情况需要把它放在body第一层去渲染,比如uc浏览器,或其它一些浏览器或环境,有更好的浏览器兼容性。
this.props.children // 对应vue中的slot 这里值为"Modal 内容"
<PortalsDemo>Modal 内容</PortalsDemo>
// DOM操作需要引入ReactDOM
return ReactDOM.createPortal(
<div className="modal">{this.props.children}</div>,
document.body // 第二个参数传入一个DOM 节点
)
2.3.2 Portals使用场景:
overflow:hidden;// 父组件设了BFC,会限制子组件的布局,可以用Portals让子组件逃离父组件- 父组件
z-index值太小; - fixed需要放在body第一层级
- 虽然利用Portal可以把组件渲染到别的地方,但是它在React中的组件结构还是一样的。
2.4 是否用过React Context
- 公共信息(语言、主题)如何传递给每个组件?
- 用props太繁琐
- 用redux小题大做,过度设计
生产:
//创建Context 填入默认值(任何一个js变量)
const ThemeContext = React.createContext('light')
管理:
// 然后在最外层使用
<ThemeContext.Provider value = {this.state.theme}>
</ThemeContext.Provider>包裹起来
// 可以通过绑定的value修改默认值
消费:
class组件
在定义完组件class之后
//指定contextType读取当前的theme context
ThemedButton.contextType = ThemeContext
另一种写法:(ES6新语法)
static contextType = ThemeContext
这两种写法都是定义一个静态属性
//指定完之后通过this.context消费
// React会往上找到最近的theme Provider
const theme = this.context
2.5 React如何异步加载组件
- 异步组件:(React一般用后两种)
- import()
- React.lazy
- React.Suspense
- 使用
const ContextDemo = React.lazy( () => import('./ContextDemo') )
然后引用这个异步组件<ContextDemo>
异步加载过程中可能会出现等待的情况,可以使用React.Suspense包裹异步组件,fallback中定义一个标签或组件,用来在加载过程中的提示显示。
2.6 React性能优化-SCU的核心问题在哪里
- shouldComponentUpdate (简称SCU)
- PureComponent 和 React.memo
- 不可变值immutable.js
2.6.1 SCU的基本用法
- SCU默认值返回的是true(可以渲染),还给了我们返回false(不重复渲染)的可定制的权利
-
2.6.2 React性能优化-SCU默认返回什么
在React的逻辑里面,如果没有做任何优化,只要父组件有更新,子组件也会无条件也进行更新,不管子组件的数据有没有变化。
如果没有定义SCU,SCU会默认返回true。
有些情况下,因为React的这个默认机制,而导致的性能问题,就需要在SCU中优化。
性能优化对于React更加重要!(react和vue的机制不一样)
SCU一定要每次都用吗?——不一定,需要的时候才优化
React性能优化-SCU一定要配合不可变值
2.6.3 如果setState没有遵循不可变值的原则:
- 这里list数组push之后,list已经发生改变,当再setState时,前后两个的list值已经一样了。
- 所以会造成SCU中的前后值判断相等,返回false,不会重新渲染。
2.6.4 SCU 使用总结
- SCU 默认返回true,即React 默认重新渲染所有子组件
- 必须配合“不可变值”一起使用
- 可以先不用SCU,有性能问题时再考虑使用
2.7 React性能优化-PureComponent和memo
2.7.1 PureComponent(纯组件) 和 memo
- PureComponent,SCU中实现了浅比较(也是需要配合不可变值的)
- memo,函数组件中的PureComponent
- 浅比较已适应大部分情况(尽量不要做深度比较)
- class组件用PureComponent,函数组件用memo
2.7.2 PureComponent 的使用:
- class List extends React.PureComponent{}
- 相当于隐藏了一个SCU,里面进行了浅比较。
2.7.3 memo 的使用:
2.8 React性能优化-了解immutable.js
2.8.1 immutable.js:
- 彻底拥抱“不可变值”;
- 基于共享数据(不是深拷贝),速度好;
- 有一定学习和迁移成本,按需使用;
const map1 = Immutable.Map({a:1,b:2.c:3})
const map2 = map1.set('b', 50)
map1.get('b') // 2
map2.get('b') // 50
2.9 什么是React高阶组件
2.9.1 关于组件公共逻辑的抽离:
-
- mixin,已被React弃用;
-
- 高阶组件HOC;(high order components)
- 高阶组件HOC;(high order components)
- 透穿所有prps (接收的props 的值都 透传给子组件)(Vue $props v-bind)
- 增加mouse属性
<Component {...this.props} mouse={this.state}/>
-
- Render Props;
2.10 redux connect是高阶组件
- 作用:连接React组件与 Redux store
mapStateToProps(state, ownProps) : stateProps
mapDispatchToProps(dispatch, ownProps): dispatchProps
- connect 源码
2.11 什么是React Render Props
- Render Props(只适用于React)
- Mouse组件
- App组件通过props接收a
2.12 HOC vs Render Props
- HOC: 模式简单,但会增加组件层级
- Render Props: 代码简洁,学习成本较高
- 按需使用
2.13 Redux考点串讲
- 和Vue 作用相同,但比Vuex 学习成本高
- 不可变值,纯函数
- 面试常考
Redux 使用
- 基本概念
- 单项数据流(画单向数据流图,经常考)
- react-redux(redux怎么连接react,考点不多,但要知道)
- 异步action(常考)
- 中间件(考察频率不高,但要知道)
相关内容
- redux
- store
- reducer
- action
- dispatch
- 单向数据流模型
- 中间件redux-thunkredux-saga
- react-redux
- provider
- connect
- mapStateToProps
- mapDispatchToProps
- react-router
2.14 描述Redux单项数据流
单项数据流概述:
- dispatch(action)
- reducer -> newState
- subscribe 触发通知
2.15 串讲react-redux知识点
react - redux:
<Provider>- connect
- mapStateToProps mapDispatchToProps
通过react-redux插件引入Provider,Provider是一个react组件。
//createStore中传入的是reducer
let store = createStore(todoAPP)
//在Provider中传入store,这样里面的所有组件都有了store的能力
<Provider store={store}></Provider>
函数组件 AddTodo ,接收 props 参数
通过结构的写法,{dispatch} 即 props.dispatch
- 在各个组件组件中想要消费redux的能力,需要把定义好的组件通过connect包裹一下,返回高阶组件。
- connect 高阶组件,(connect 包裹组件之后,就已经)将 dispatch 作为 props 注入到 AddTodo组件中
2.16 React原理-考点串讲
2.16.1 再次回顾不可变值
2.16.2 vdom和diff是实现React的核心技术
- vdom
- h函数
- Vnode 数据结构
- patch 函数
- diff 算法
- 只比较同一层级,不跨级比较
- tag不相同,则直接删掉重建,不在深度比较
- tag 和 key,两者都相同,则认为是相同节点,不在深度比较
2.16.3 JSX本质是什么
- JSX 等同于Vue 模板
- Vue 模板不是html
- JSX 也不是JS
2.16.4 JSX 本质
React.createElement即h函数,返回vnode- 第一个参数,可能是组件,也可能是html tag
- 组件名,首字母必须大写(React 规定)
2.17 说一下React的合成事件机制
2.17.1合成事件
- 所有事件挂载到document 上
- event 不是原生的,是SyntheticEvent 合成事件对象
- (event 其实是React 封装)可以使用__proto__.constructor
- 和Vue事件不同,和DOM事件也不同
2.17.2 为何要合成事件机制?
- 更好的兼容性和跨平台
- 载到document,减少内存消耗,避免频繁解绑
- 方便事件的统一管理(如事务机制)
2.18 说一下React的batchUpdate机制
- 有时异步(普通使用),有时同步(setTimeout, DOM事件)
- 有时合并(对象形式),有时不合并(函数形式)
- 后者比较好理解(像Object.assgin)
2.19 setState 异步还是同步?
- setState 无所谓同步还是异步
- 看是否命中batchUpdate 机制
- 判断isBatchingUpdates
哪些能命中 batchUpdate 机制
- 生命周期(和它的调用函数)
- React 中注册的事件(和它调用的函数)
- React 可以“管理”的入口
哪些不能命中 batchUpdate 机制
- setTimeout setInterval 等(和它调用的函数)
- 自定义的DOM 事件(和它调用的函数)
- react "管不到"的入口
2.20 简述React事务机制
2.21 说一下React组件渲染和更新的过程
1. JSX本质和vdom
- JSX 即createElement 函数
- 执行生成vnode
- patch(elem, vnode) 和 patch(vnode, newVnode)
2. 组件渲染过程
- props state
- render() 生成 vnode
- patch(elem, vnode)
3. 组件更新过程
- setState(newState) --> dirtyCompontents(可能有子组件)
- render() 生成newVnode
- patch(elem, newVnode)
2.22 React-fiber如何优化性能
1. patch 被拆分两个阶段
- reconciliation 阶段 - 执行diff 算法,纯JS 计算
- commit 阶段 - 将diff 结果渲染DOM
2. 可能会有性能问题
- JS 是单线程,且和DOM 渲染公用一个线程
- 当组件足够复杂,组件更新时计算和渲染都压力巨大
- 同时再有DOM 操作需求(动画、鼠标拖拽等),将卡顿
3. 解决方案 fiber
- 将 reconciliation 阶段进行任务拆分(commit无法拆分)
- DOM 需要渲染时暂停,空闲时恢复
- window.requestIdleCallback
4. 关于fiber
- React 内部运行机制,开发者体会不到
2.23 React原理-总结
- 函数式编程
- vdom 和 diff
- JSX 本质
- 合成事件
- setState batchUpdaet
- 组件渲染过程
- 前端路由
2.24 React真题演练-1-组件之间如何通讯
组件之间如何通讯
- 父子组件 props
- 自定义事件
- Redux 和 context
JSX 本质是什么?
- createElement
- 执行返回Vnode
Context 是什么,如何应用?
- 父组件向其所有子孙组件传递信息
- 如一些简单的公共信息:主题色、语言等
- 复杂的公共信息,请用redux
shouldCompontentUpdate 用途
- 性能优化
- 配合“不可变值”一起使用,否则会出错
redux 单向数据流
2.25 React真题演练-2-ajax应该放在哪个生命周期
setState 场景题
什么是纯函数
- 返回一个新值,没有副作用(不会“偷偷”修改其他值)
- 重点: 不可变值
- 如:arr1 = arr.slice()
React 组件的生命周期
- 单组件的生命周期
- 父子组件的生命周期
- 注意SCU
ajax应该放在哪个生命周期?
- 同Vue
- componentDidMount
渲染列表,为何使用key
- 同Vue,必须使用key,且不能是index 和 rendom
- diff算法通过tag 和 key 来判断,是否是sameNode
- 减少渲染次数,提升渲染性能
2.26 React真题演练-3-组件公共逻辑如何抽离
函数组件和class 组件的区别
- 纯函数组件,输入props,输出JSX
- 没有实例,没有生命周期,没有State
- 不能扩展其他方法
什么是受控组件
- 表单的值,受State控制
- 需要自行监听onChange,更新state
- 对比非受控组件
何时使用异步组件
- 同Vue
- 加载大组件
- 路由懒加载
多个组件有公共逻辑,如何抽离
- 高阶组件(HOC)
- render Props
- mixin已被react 废弃
redux 如何进行异步请求
- 使用异步action
- 如redux-thunk
2.27 React真题演练-4-React常见性能优化方式
react-router 如何配置懒加载
pureCmpontent 有何区别
- 实现了浅比较的shouldComponentUpdate
- 优化性能
- 但要结合不可变值使用
React 事件和DOM事件的区别
- 所有事件挂载到document上
- Event 不是原生的,是SyntheticEvent 合成事件对象
- dispatchEvent
React 性能优化
- 渲染列表时 key
- 自定义事件、DOM事件及时销毁
- 合理使用异步组件
- 减少函数bind this的次数
- 合理使用SCU PrueCompontent 和 memo
- 合理使用Immutable.js
- webpack 层面的优化
- 前端通用的性能优化,如图片懒加载
- 使用SSR
2.28 React真题演练-5-React和Vue的区别
- 都支持组件化
- 都是数据驱动视图
- 都使用vdom 操作DOM
- React 使用JSX拥抱JS,Vue使用模板拥抱html
- React 函数式编程,Vue声明式编程
- React 更多需要自力更生,Vue 把想要的都给你