可能是异步,可能会合并?
react <=17 中:
react 18中:
import PropTypes from 'prop-types'
// PropTypes.arrayOf(PropTypes.string, PropTypes.number) // 数据为数组时,数组的元素可以是什么类型
// PropTypes.oneOfType(PropTypes.string, PropTypes.number) // 数据可以是string,也可以是number
// 设置类型
TodoItem.propTypes = {
test: PropTypes.string.isRequired, // test
content: PropTypes.string,
index: PropTypes.number,
deleteItem: PropTypes.func
}
// 设置默认值
TodoItem.defaultProps = {
test: 'test'
}
shouldComponentUpdate:可在此生命周期函数中判断子组件是否需要更新,从而提升性能
shouldComponentUpdate(nextProps, nextState) {
console.log('child', 'shouldComponentUpdate')
if (nextProps.content === this.props.content) {
return false
} else {
return true
}
}
componentDidMount:可在此生命周期函数中发送ajax请求数据
1、使用 createRef创建 ref
2、使用函数创建
<input
id="input"
value={this.state.inputValue}
onChange={this.handleInputChange}
ref={(input) => this.input = input}
></input>
比普通组件性能更好
因为无状态组件只是一个函数,而普通组件是一个class类,需要执行生命周期和render函数
所以,如果组件中只有render函数时,可以使用无状态组件
ReactDOM.createPortal
使用场景:
将公共信息传递给每个组件
import { Component, createContext } from 'react
const ThemeContext = createContext('light')
// 父级
// ...
return <ThemeContext.Provider value={this.state.theme}>
// ...
</ThemeContext.Provider>
// ...
// 子级(class 组件)
class ThemeButton extends Component {
// static contextType = ThemeContext
render() {
const theme = this.context
return <div>{theme}</div>
}
}
ThemeButton.contextType = ThemeContext
// 函数组件
const ThemeLink = () => {
return <ThemeContext.consumer>
{ value => <p>{value}</p> }
</ThemeContext.consumer>
}
高阶组件不是一种功能,而是一种模式,实现组件之间的公共逻辑抽离
const HOCFactory = (Component) => {
class HOC extends React.Component {
// 公共逻辑...
render () {
return <Component {...this.props} />
}
}
}
export default HOCFactory(WrapperComponent)
与 render props 相比,模式简单,但会增加组件层级
实现之间的逻辑抽离
class Mouse extends Component {
// 公共逻辑...
render () {
return {this.props.render(this.state)}
}
}
class App extends Component {
render () {
return <Mouse render={(props) => <p>{props.x}{props.y}</p>}>
}
}
与 HOC 相比,代码简洁,学习成本较高
class 组件的问题
React 组件更易用函数表达
Hooks 命名规范
// 语法:
useEffect(() => {})
// 语法:
useEffect(() => {}, [])
// 语法1:
useEffect(() => {})
// 语法2:
useEffect(() => {}, [a, b])
// 语法:
// 模拟 DidMount
useEffect(() => {
// 模拟 WillUnMount
return () => {
// ...组件销毁时的一些逻辑
}
}, [])
模拟 componentWillUnMount 但不完全相等
useEffect 让纯函数有了副作用
const btnRef = useRef(null) // 初始值
useEffect(() => {
console.log(btnRef.current) // dom节点
})
return <button ref={btnRef}>按钮</button>
import { Component, createContext, useContext } from 'react
const ThemeContext = createContext('light')
// 父级
// ...
return <ThemeContext.Provider value={this.state.theme}>
// ...
</ThemeContext.Provider>
// ...
// 函数组件
const ThemeLink = () => {
const theme = useContext(ThemeContext)
return <p>{theme}</p>
}
const [state, dispatch] = useReducer(reducer, initialState)
useReducer 和 redux 的区别
// 子组件用 memo 包裹
const Child = memo(() => {})
// 父组件
const App = () => {
const [name, setName] = useState('zhangsan')
// useMemo 缓存数据
const userInfo = useMemo(
() => ({name, age: 20}),
[name]
)
return <Child userInfo={userInfo} />
}
// 子组件用 memo 包裹
const Child = memo(() => {})
// 父组件
const App = () => {
const [name, setName] = useState('zhangsan')
// useMemo 缓存数据
const userInfo = useMemo(
() => ({name, age: 20}),
[name]
)
// useCallback 缓存函数
const handleChange = useCallback(() => {
// ...
}, [])
return <Child userInfo={userInfo} handleChange={handleChange} />
}
Mixins 的问题
高阶组件 HOC
Render props
React.createElement(tag/component, props/null, [child, child]/child, child),类似vue的h函数,执行后返回vnode,执行patch函数生成dom
为何要合成事件机制?
更新:
setState 是异步还是同步?
transaction 事务机制
组件渲染过程
组件更新过程
path 更新的两个阶段
可能会有性能问题
解决方案 fiber
createStore:创建store
store.dispatch:派发action
store.getState:获取store所有的数据
store.subscribe:订阅store的改变,store发生改变,subscribe中接受的回调函数就会被触发
注:
reducer 可以接受state,但是绝不能修改state
reducer 必须是纯函数,给定固定的输入,就一定会有固定的输出,而且不会有任何副作用
中小型项目中使用,异步请求或者非常复杂的逻辑,可以放到redux-thunk中统一管理
可以在action中写函数
大型项目中可使用该库进行action管理
在react组件中方便操作store
管理store中的数据,防止不小心直接在reducer中改变state的值(彻底拥抱“不可变值”)
如果使用pureComponent需要使用immutable管理数据
Api:
在react中编写样式,区分在组件中生效还是全局生效
路由
动画库
相同点
不同点