通过这周需求的开发,我发现本身在编写代码的过程当中不太关注代码的复用性和可维护性,不经意间就直接简单的复制粘贴就完事,这样看起来是实现了功能,可是却为之后的开发留下了很大的隐患。因此,这周我特意结合了本身开发过程当中的问题,简单了了解了一下关于提升React代码复用性的两种方法。react
先介绍一下什么是React的高阶组件,设计模式
高阶组件是一个函数,接收一个组件,而后返回一个新的组件。数组
const EnhancedComponent = highOrderComponent(WrappedComponent);
要记住的是,虽然名称是高阶组件,可是高阶组件不是组件,而是函数!app
既然是函数,那就能够有参数,有返回值。从上面能够看出,这个函数接收一个组件WrappedComponent做为参数 ,返回加工过的新组件EnhancedComponent。其实高阶组件就是设计模式里的装饰者模式。函数
能够说,组件是把 props 转化成 UI,而高阶组件是把一个组件转化成另一个组件。this
下面是一个简单的高阶组件:设计
import React, { Component } from 'react'; export default (WrappedComponent) => { return class EnhancedComponent extends Component { // do something render() { return <WrappedComponent />; //HOC返回的是一个新的组件 } } }
其实,这只是其中的一种高阶组件,这个时候高阶组件复用的是组件,也就是说在一个通用的组件中添加额外的逻辑,而后返回一个添加了额外方法和参数的新组件。code
另一种高阶组件复用的是多个组件中相同的逻辑,返回一个新的组件。我在开发中使用到的就是这种形式的高阶组件。它是这样的形式:component
//组件一 class Component1 extends React.Component { ... } //组件二 class Component2 extends React.Component { ... } //假设组件一和组件二都须要使用相同的函数foo //设计一个能够复用foo的高阶组件 const HOCComponent = (Component, props) => { const obj = { foo1() {}, foo2() {}, ... //这里表示想添加的其余参数 }; const newprops = Object.assign({}, obj, props); return <Component {...newprops}/> } //使用该高阶组件 let newComponent1 = HOCComponent(Component1, this.props); let newComponent2 = HOCComponent(Component2, this.props);
这样就能够实现复用两个组件相同的函数或者其余的参数了,不用在每一个组件中都写重复的代码。开发
先简单介绍一下useState这个hook,
用法:
const [state, setState] = useState(initialState);
返回值:state,更新state的函数setState
参数:初始的state:initialState
由于useState这个Hook诞生以前,若是想使用state必须得定义类组件,函数组件没法使用state,可是组件的演变确定是往轻量化这个方向演变的,因此useState就能够是函数组件也可使用state。
来看一下下面这个例子:
有一个这样的场景:
如今有 小A,小B 两位同窗,每位同窗都处于未穿鞋的状态,小A穿鞋须要2s,小B穿鞋须要5s,在页面一中用文字描述两位同窗的穿鞋状态变动( 若是小A正在穿鞋中,则在页面上显示 '小A正在穿鞋子',若是小A已经穿好了鞋子,则将文字替换为 '小A已经穿好鞋子')
使用class组件实现是这样的:
import React from "react"; class Page extends React.Component { state = { data: [ { id: 1, name: "小A", time: "2000" }, { id: 2, name: "小B", time: "5000" } ] }; start(item) { this.setState({ [item.id]: "穿鞋子" }); setTimeout(() => { this.setState({ [item.id]: "穿好鞋子" }); }, item.time); } componentDidMount() { this.state.data.forEach(item => { this.start(item); }); } render() { return ( <div> {this.state.data.map(item => { return ( <h1 key={item.id}> {this.state[item.id] === "穿鞋子" ? `${item.name}正在穿鞋子...` : `${item.name}已经穿好鞋子了`} </h1> ); })} </div> ); } } export default Page;
使用Hook组件实现是这样的:
自定义Hook以下:
import React, { useState } from "react"; function useHook(item) { const [status, setStatus] = useState("穿鞋子"); setTimeout(() => { setStatus("穿好鞋子"); }, item.time); return ( <h1 key={item.id}> {status === "穿鞋子" ? `${item.name}正在穿鞋子...` : `${item.name}已经穿好鞋子了`} </h1> ); } export default useHook;
引用hook的函数组件
import React from "react"; import useHook from "./useHook"; function Page() { const data = [ { id: 1, name: "小A", time: "2000" }, { id: 2, name: "小B", time: "5000" } ]; return ( <div> {data.map(item => { return useHook(item); })} </div> ); } export default Page;
看起来并无什么区别嘛,代码量也没有减小。
可是,若是小C和小D也要实现这样的描述,使用定义好的Hook就简单多了。
import React from "react"; import useHook from "./useHook"; function Page() { const data = [ { id: 1, name: "小C", time: "4000" }, { id: 2, name: "小D", time: "8000" } ]; return ( <div style={{ color: "lightblue" }}> {data.map(item => { return useHook(item); })} </div> ); } export default Page;