周末加班,临时整理些react有关的东西
1、immutable
一旦创建就不可修改的数据类型,对immutable
对象的任何修改、添加或删除操作都会返回一个新的immutable
对象。其实现原理是Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时要保证旧数据同时可用且不变。同时为了避免deepcopy(深拷贝)带来的性能损耗,immutable
使用了结构共享Structural Sharing,即如果对象树中的一个节点发生变化,只修改此节点和受影响的父节点,其他节点则进行共享。
Immutable
优点
- 降低 Mutable 带来的复杂度
- 节省内存空间
- 两个对象对比,直接对比内存地址即可,给react刷新优化带来非常大的便利
缺点:容易与原生对象搞混
2、key的作用是什么
key是react用来追踪节点被修改、添加或移除的标识,react的diff算法会根据节点的key值判断该节点是否需要刷新,以减少不必要的渲染。一般适用在列表组件的子项里,需保证同级元素key值的唯一性。在某些时候,甚至能直接改变组件的key值来达到重新渲染整个组件的目的。
3、调用setState发生了什么
setState一般用来更新数据,重新渲染DOM元素。调用setState后,react会将参数对象合并到当前状态,发起一个和解过程(reconciliation),以高效的方式生成一个新的元素树,之后通过diff算法计算两个元素树的不同点,进行最小差异化渲染。
4、生命周期
constructor 初始化
componentWillMount
componentDidMount
shouldComponentUpdate
componentWillUnmount
render
componentWillReceiveProps
5、diff算法
1、把树形结构按层级分解,只比较同层级元素
2、按照key值来比较同级元素
3、react只匹配相同class的component,不同则直接删除然后挂载新的节点
4、合并操作
5、选择性的渲染
6、redux
三个原则
- 单一数据源
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
- State 是只读的
唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
- 使用纯函数来执行修改
由用户交互触发 -----> action ----(store.dispatch(action)
)---- > store ----(store调用reducer返回新的state
)-----> reducer -----> view刷新
redux原理、同步异步如何实现、中间件的原理
中间件:react-logger、react-thunk。
异步action实现:
在store.dispatch中传入一个函数执行,这个函数返回另一个函数,参数有两个,一个是dispatch、另一个则是getState,然后在这个函数中进行异步操作,分别在异步开始、成功、失败步骤中调用传入的dispatch方法,传入相应的action;因为需要dispatch一个函数,所以需要使用react-thunk配合。
applyMiddleware的实现原理:
使用柯里化函数来保存参数,如果有中间件则会传入createStore,在返回的函数里面构建store,生成每个中间件都需要的dispatch和getState,再遍历middlewares中间件数组,分别调用每个中间件一次。
第三个参数通过applyMiddleware添加中间件。
通过connect(mapStateToProps, mapDispatchToProps)(组件) 可以访问到store里面特定的state和action,避免因为监听所有state变化造成性能问题。在mapDispatchToProps里面可以用bindActionCreators把dispatch和action creator绑定在一起,这样就直接调用action creator函数就相当于直接dispatch了
7、Hooks
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。
React内置两种hook:stateHook与effectHook。
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
You clicked {count} times
);
}
stateHook
对function
组件提供state
支持,使函数组件可以使用state
更新数据。useState
参数只有一个,就是初始state
,其返回一个数组包含变量名与更新函数,这里使用了数组解构获取count
与setCount
,之后就可以直接使用setCount
更新count
的值。
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
You clicked {count} times
);
}
effectHook是每次组件更新都会调用的一个hook,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate
和 componentWillUnmount
这三个函数的组合。也可以在useEffectHook
中返回一个函数,做一些扫尾工作,React 将会在执行清除操作时调用它。
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
userEffectHook
还能传入第二个参数,已达到性能优化的目的。
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新
第二个参数为一个数组,表示仅当数组中的数据发生改变是,才执行effect
。
8、Context
避免繁琐的props或者state的逐级传递,可以跨组件传递数据。通过createContext
创建上下文对象,context
对象主要是有provide(生产者)
和consumer(消费者)
。使用provide
包裹父组件,传入value
值;consumer
包裹子组件,并使用function child
的方式返回需要渲染的React节点,完成context
订阅。Provider 及其内部 consumer 组件都不受制于shouldComponentUpdate
函数。
{value => /* 基于 context 值进行渲染*/}
9、refs
refs提供了一种访问dom节点或react element
的方法,我们可以使用它来播放视频、管理焦点、触发命令式动画等操作。
10、webpack
四个核心概念:
1. 入口(entry)
告诉webpack从哪里开始打包,从入口开始webpack会找出所有依赖的文件。可以有多个入口。
entry: {
main: './path/to/my/entry/file.js'
}
2. 输出(output)
告诉webpack在哪里输出它所创建的bundle,以及如何命名这些文件。我们通过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里
output: {
filename: 'my-first-webpack.bundle.js'
},
3. loader
将所有类型的文件转换为 webpack 能够处理的有效模块。
在 webpack 的配置中 loader 有两个目标:
- test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
- use 属性,表示进行转换时,应该使用哪个 loader。
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
}
4. 插件(plugins)
loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
想要使用一个插件,你只需要 require()
它,然后把它添加到 plugins
数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new
操作符来创建它的一个实例。
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
11、高阶组件HOC
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
具体而言,高阶组件是参数为组件,返回值为新组件的函数。
12、容器组件和展示组件
展示组件其实就相当于可控状态组件,由外部控制其界面展示,没有内部state
。
容器组件为展示组件或其他组件提供数据和方法,通常由高阶组件生成,比如Redux里的connect(),Relay里的createContainer()。