什么是高阶组件
高阶组件(HOC)就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件
高阶函数
高阶组件其实有点类似与高阶函数,高阶函数是接收一个或多个函数作为参数,并返回一个函数
举例
有两个方法,一个welcome,一个goodbye。两个函数先从localStorage 读取了username,然后对 username 做了一些处理
普通实现
function welcome() {
let username = localStorage.getItem('username');
console.log('welcome ' + username);
}
function goodbey() {
let username = localStorage.getItem('username');
console.log('goodbey ' + username);
}
welcome();
goodbey();
这样书写后发现两个函数有一句代码是重复的;所以我们就可以写一个中间函数,来解决这个问题。这个中间函数的作用就是,读取 username 病 复杂把 username 传递给这两个函数
function welcome(username) {
console.log('welcome ' + username);
}
function goodbey(username) {
console.log('goodbey ' + username);
}
function wrapWithUsername(wrappedFunc) {
let newFunc = () => {
let username = localStorage.getItem('username');
wrappedFunc(username);
};
return newFunc;
}
welcome = wrapWithUsername(welcome);
goodbey = wrapWithUsername(goodbey);
welcome();
goodbey();
这里的函数 wrapWithUsername 就是一个高阶函数,它帮我们处理了 username,传递给目标函数。我们调用最终的函数 welcome 的时候,根本不用关心 username 是怎么来的
这就有点类似于 react-router 中的 withRouter
,我们不关心是如何实现的,只关心我们想要的结果
高阶组件的使用
props 的增强
不修改原有代码的情况下,添加新的props
class Header extends PureComponent {
render() {
const { name, age } = this.props;
return <h2>Header {name + age}</h2>
}
}
export default class App extends PureComponent {
render() {
return (
<div>
<Header name="aaa" age={18} />
</div>
)
}
}
function enhanceProps(WrapperCpn, otherProps) {
return props => <WrapperCpn {...props} {...otherProps} />
}
const EnhanceHeader = enhanceProps(Header, {height: 1.88})
利用高阶组件来共享Context属性
import React, { PureComponent, createContext } from 'react';
const UserContext = createContext({
nickname: "默认",
level: -1
})
function Header(props) {
return (
<UserContext.Consumer>
{
value => {
const { nickname, level } = value;
return <h2>Header {"昵称:" + nickname + "等级" + level}</h2>
}
}
</UserContext.Consumer>
)
}
function Footer(props) {
return (
<UserContext.Consumer>
{
value => {
const { nickname, level } = value;
return <h2>Footer {"昵称:" + nickname + "等级" + level}</h2>
}
}
</UserContext.Consumer>
)
}
const EnhanceHeader = enhanceProps(Header, { height: 1.88 })
export default class App extends PureComponent {
render() {
return (
<div>
<UserContext.Provider value={{ nickname: "hhh", level: 90 }}>
<Header />
<Footer />
</UserContext.Provider>
</div>
)
}
}
再次优化
import React, { PureComponent, createContext } from 'react';
const UserContext = createContext({
nickname: "默认",
level: -1
})
function withUser(WrapperCpn) {
return props => {
return (
<UserContext.Consumer>
{
value => {
return <WrapperCpn {...props} {...value}/>
}
}
</UserContext.Consumer>
)
}
}
function Header(props) {
const { nickname, level } = props;
return <h2>Header {"昵称:" + nickname + "等级:" + level}</h2>
}
function Footer(props) {
const { nickname, level } = props;
return <h2>Footer {"昵称:" + nickname + "等级:" + level}</h2>
}
const UserHeader = withUser(Header);
const UserFooter = withUser(Footer);
export default class App extends PureComponent {
render() {
return (
<div>
<UserContext.Provider value={{ nickname: "why", level: 90 }}>
<UserHeader />
<UserFooter />
</UserContext.Provider>
</div>
)
}
}
渲染判断鉴权
import React, { PureComponent } from 'react';
function loginAuth(Page) {
return props => {
if (props.isLogin) {
return <Page/>
} else {
return <LoginPage/>
}
}
}
function LoginPage() {
return <h2>LoginPage</h2>
}
function CartPage() {
return <h2>CartPage</h2>
}
const AuthCartPage = loginAuth(CartPage);
export default class App extends PureComponent {
render() {
return (
<div>
<AuthCartPage isLogin={true}/>
</div>
)
}
}
生命周期劫持
import React, { PureComponent } from 'react';
function logRenderTime(WrapperCpn) {
return class extends PureComponent {
UNSAFE_componentWillMount() {
this.begin = Date.now();
}
componentDidMount() {
this.end = Date.now();
const interval = this.end - this.begin;
console.log(`${WrapperCpn.name}渲染使用时间:${interval}`)
}
render() {
return <WrapperCpn {...this.props}/>
}
}
}
class Home extends PureComponent {
render() {
return (
<div>
<h2>Home</h2>
<p>我是home的元素,哈哈哈</p>
</div>
)
}
}
class Detail extends PureComponent {
render() {
return (
<div>
<h2>Detail</h2>
<p>我是detail的元素,哈哈哈</p>
</div>
)
}
}
const LogHome = logRenderTime(Home);
const LogDetail = logRenderTime(Detail);
export default class App extends PureComponent {
render() {
return (
<div>
<LogHome />
<LogDetail />
</div>
)
}
}
后天就要科四了,冲冲冲!!!!
精准学习法。。。。哈哈哈哈哈哈