Skip to content

高阶组件 ​

本节目标:理解“高阶组件”的核心思路,并能把它用于实际开发或面试表达。

**高阶函数:**
let fn = () => () => () => {
//code
}

高阶组件: 一个组件返回一个组件

**1.****为什么需要高阶组件**
==我们先看一个非常常见的例子,一个输入框需要从本地获取数据将获取的数据放到输入框内==
export default class Username extends React.Component {
constructor() {
super();
this.state = { val: '' }
}
componentDidMount() {
let username = localStorage.getItem('username') || '';
this.setState({
val: username
})
}
render() {
return
<div>
<input type="text" value={this.state.val} onChange={() => { }} />
</div>
}
}

这段逻辑可能在Password组件中也要使用,那么从本地存储中获取数据放到输入框内的逻辑应该就是公用逻辑。这时我们就要使用高阶组件,也就是将组件在原有的基础上进行包装。

**2.实现高阶组件**
import React from 'react';
let local = (key) => (Component) => {
return class HighOrderComponent extends React.Component {
constructor() {
super();
this.state = { [key]: '' }
}
componentDidMount() {
let val = localStorage.getItem(key) || '';
this.setState({
[key]: val
})
}
render() {
return <Component {...this.state} />
}
}
};
export default local;
//使用
import Local from './Local'
class Username extends React.Component {
render() {
return <div>
<input type="text" value={this.props.val} onChange={() => { }} />
</div>
}
}
//告诉local将username取出来,以属性的方式传递给username
export default Local('username')(Username);
==我们将公共的逻辑拿到外层组件,处理好后以属性的方式传递给原本的组件,为此高阶组件就是一个 React 组件包裹着另外一个 React 组件==
**4.使用react-redux实现todo**
==Todos |-> TodoHeader======      ==|-> TodoItems======      ==|-> TodoFooter======
**5.实现react-redux库**
**react-redux计数器**
==和以前写过的逻辑一致,这回加上react-redux的逻辑==
==import React from 'react';========import ReactDOM from 'react-dom';========import Counter from "./components/Counter";========import store from './store/index';========import {Provider} from 'react-redux';========ReactDOM.render(======  ==<Provider store={store}>======    ==<Counter/>======  ==</Provider>,window.root);======
==// counter组件========class Counter extends React.Component {======  ==render(){======    ==return <div>======      ==数量:{this.props.number}======      ==<button onClick={()=>{this.props.add(1)}}>+</button>======      ==<button  onClick={()=>{this.props.minus(1)}}>-</button>======      ==</div>======  ==}========}========export default connect(state=>({...state}),dispatch=>({======  ==add:(amount)=>{dispatch(actions.add(amount))},======  ==minus:(amount)=>{dispatch(actions.minus(amount))}========}))(Counter)======
**编写react-redux库**
==import React from 'react';========import PropTypes from 'prop-types';========class Provider extends React.Component{======  ==static childContextTypes = {======    ==store:PropTypes.object======  ==};======  ==getChildContext(){======    ==return {store:this.props.store}======  ==}======  ==constructor(){======    ==super();======  ==}======  ==render(){======    ==return this.props.children;======  ==}========}========let connect = (mapStateToProps,mapDispatchToProps) => (Component) =>{======  ==return class Proxy extends React.Component{======    ==static contextTypes = {======      ==store:PropTypes.object======    ==};======    ==componentDidMount(){======      ==this.unsubscribe = this.context.store.subscribe(()=>{======        ==this.setState(mapStateToProps(this.context.store.getState()))======      ==});======    ==}======    ==componentWillUnmount(){======      ==this.unsubscribe();======    ==}======    ==constructor(props,context){======      ==super();======      ==this.state = mapStateToProps(context.store.getState());======    ==}======    ==render(){======      ==return <Component {...this.state} {...mapDispatchToProps(this.context.store.dispatch)}/>======    ==}======  ==}========};========export {Provider,connect}======
**bindActionCreators方法**
==let bindActionCreators = (actions,dispatch) => {======  ==let obj = {}======  ==for(let key in actions){======    ==obj[key] = (...args)=>{======      ==dispatch(actions[key](...args))======    ==}======  ==}======  ==return obj========};======
==export default connect(state=>({...state}),dispatch=>bindActionCreators(actions,dispatch))(Counter)======
==bindActionCreators是redux中的一个方法,并且这样的逻辑过于复杂,我们依旧希望可以在react-redux中内部可以简化操作==
**简化mapDispatchToProps**
==export default connect(state=>({...state}),actions)(Counter);======
==import {bindActionCreators} from './redux'========render(){======  ==let r ={}======  ==if(typeof mapDispatchToProps === 'object'){======    ==r = bindActionCreators(mapDispatchToProps,this.context.store.dispatch)======  ==}else{======    ==r = mapDispatchToProps(this.context.store.dispatch)======  ==}======  ==return <Component {...this.state} {...r}/>========}======
==这样我们在组件中更改状态时可以直接传入actionCreator对象。==

> 来自 <https://zhufengzhufeng.github.io/zhufengreact/html/React-Redux.html#t11.%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81%E9%AB%98%E9%98%B6%E7%BB%84%E4%BB%B6>

本站总访问 — 次