React设计模式与场景分析
时间:2023-04-02 23:45:18
HTML
本周连续发表了两篇关于React的文章:组件重用的那些事儿——React实现轮子的按需加载React应用设计——CurryMagicUse涉及到React组件重用,轮子设计相关话题,并结合相关场景实例进行分析。这些内容都是React设计模式。谈到设计模式,读者不必害怕。其实这就是React开发应用灵活性的体现。在今天的文章中,我们继续通过一个场景,一步一步,通过一步步优化设计来加深理解。场景介绍界面左侧大面积显示区块内容,点击继续按钮可切换到下一条内容信息;右侧是导航栏,表示当前块显示的信息项。如果看Gif图片还不够,可以去CodeSandbox在线了解一下。具体代码结构为:classAppextendsComponent{render(){return();}}Stepper组件的'stage'属性表示默认的起始块,也使用与'stage''state相同的名称。这里的舞台代表左边的内容块。handleClick方法切换this.stata.stage。classStepperextendsComponent{state={stage:this.props.stage}staticdefaultProps={stage:1}handleClick=()=>{this.setState({stage:this.state.stage+1})}render(){const{stage}=this.state;return(
);我们看到Stepper组件包含Progress组件(左侧导航)和Steps组件。这样的代码运行良好,但在可重用性和灵活性方面存在一些问题。例如:如果我们需要切换Progress和Steps组件的显示顺序(左右)怎么办?如果我们的步进器需要承载更多阶段怎么办?如果我们需要更改某个阶段的内容怎么办?如果我们想切换阶段的顺序怎么办?基于现有代码,这些问题都可以解决。但是需要重新更改组件写入内容。如果哪天增加了新的或调整的需求,组件内容也需要重写。接下来,我们用另一种方式来实现需求,让代码更加灵活和可重用。重新设计仔细观察Stepper组件:它包含当前块阶段,以及更改阶段的方法,渲染两个子组件。我们使用FunctionasChildComponent来重构Stepper组件。(如果对FunctionasChildComponent不熟悉,可以参考我之前的文章ComponentReuseThings-ReactImplementsLoadingWheelsonDemand)如下图:Progress和Steps组件不再直接出现在组件的render方法中步进器组件。我们使用this.props.children渲染Stepper组件的所有子组件。这样,Stepper组件渲染的内容就更加灵活了。但是,仅靠这样的修改是不可能完成需求的。当用户点击继续按钮时,舞台不会切换。因为Progress和Steps组件不再通过props感知stage和handleClick方法。为了解决这个问题,我们可以手动遍历Stepper组件的子节点,将对应的props一一注入。以下代码:constchildren=React.Children.map(this.props.children,child=>{returnReact.cloneElement(child,{stage,handleClick:this.handleClick})})使用React.Children.map来制作childnodes通过React.cloneElement方法遍历复制子组件,该方法具有通过第二个参数添加额外props的能力。Stepper组件的render方法只需要具体应用:const{stage}=this.state;constchildren=React.Children.map(this.props.children,child=>{returnReact.cloneElement(child,{阶段,handleClick:this.handleClick})})return(
{children} );现在该应用程序再次正常运行!classAppextendsComponent{render(){return(
);我们也可以将相同的方法应用到Progress组件中。这里就不一一展开了。使用静态属性值得一提的是,我们可以使用静态属性来增强代码的可读性。静态属性允许我们直接在类中调用方法。首先,我们在Stepper组件中创建两个静态方法,分别赋值给Progress组件和Steps组件:staticProgress=Progress;staticSteps=Steps现在,在App.js中我们可以直接:importReact,{Component}from'react';importStepperfrom"./Stepper"classAppextendsComponent{render(){return(
);}}导出默认应用;这样做的好处是不需要反复导入Progress组件和Steps组件,它们都会作为Stepper的静态属性出现。我个人不太喜欢这种方法。使用ReactTransitionGroup我们使用ReactTransitionGroup为Steps组件内容添加过渡动画。只有当props.num与this.props.stage等时,区块内容设置为可见:classStepsextendsComponent{render(){const{stage,handleClick}=this.propsconstchildren=React.Children.map(this.props.children,child=>{console.log(child.props)return(stage===child.props.num&&{child})})return({children}