react组件类型及应用

257 阅读3分钟

一. 引言

  • 组件是近代工业发展的产物,兴起于20世纪初,目的是功能模块化,前提是接口标准化,好处是构成产品的各个功能组件,由更专业的厂商生产,提高了质量,降低了成本。而生产组件的厂商,同样的组件,可应用于多类产品和多个领域,极大地扩展了市场范围。

二. 什么是组件

  • 概念:组件(Component)是对数据和方法的简单封装。
  • 遵循5大准则:单一职责,开闭原则,里式替换,依赖反转,迪米特法则。

三. 组件的分类及应用

1. 无状态组件

  • 无状态组件是最基础的组件形式,你可以简单理解为它就是一个无逻辑,只展示的组件。一般来说,各种UI库里也是最开始会开发的组件类别。如按钮、标签、输入框等。它的基本组成结构就是属性(props)加上一个渲染函数(render)。由于不涉及到状态的更新,所以这种组件的复用性也最强。
    • 如:fuction组件
    import React from "react";
    
    function App(props) {
      return (
        <div>
          { props.xxx }
        </div>
      );
    }
    
    export default App;
    

2. 有状态组件

  • 在无状态组件的基础上,如果组件内部包含状态(state)且状态随着事件或者外部的消息而发生改变的时候,这就构成了有状态组件(Stateful Component)。有状态组件通常会带有生命周期(lifecycle),用以在不同的时刻触发状态的更新。这种组件也是通常在写业务逻辑中最经常使用到的,根据不同的业务场景组件的状态数量以及生命周期机制也不尽相同。
    import React, { Component } from "react";
    
    export default class EventHandle extends Component {
      constructor(props) {
        super(props);
    
        this.state = {
          name: ""
        };
    
        this.handleChange = this.handleChange.bind(this);
      }
      handleChange(e) {
        this.setState({ name: e.target.value });
      }
      render() {
        return (
          <div>
            <input
              type="text"
              value={this.state.name}
              onChange={this.handleChange}
            />
            <p>{this.state.name}</p>
          </div>
        );
      }
    }    
    

3. 容器组件

  • 容器组件就是存放一个通用数据和通用逻辑的数据仓库,它符合于设计模式的中介者模式。所有相关对象都可以通过数据仓库(中介者对象)进行通信。
  • 举个例子:redux,vuex
    • store/calculation.js
    // action creator
    export const add = num => ({ type: "add", payload: num });
    // action creator
    export const minus = num => ({ type: "minus", payload: num });
    
    export const calculationReducer = (state = 0, action) => {
        const num = action.payload || 1;
        switch (action.type) {
          case "add":
            return state + num;
          case "minus":
            return state - num;
          default:
            return state;
        }
    };
    
    • store/index.js
    import { calculationReducer } from './calculation'
    import logger from "redux-logger"
    import thunk from "redux-thunk"
    
    const store = createStore(
        calculationReducer,
        applyMiddleware(logger, thunk)
    );
    
    export default store;
    
    • views/calculationNum.js
    import { add, minus, asyncAdd } from "../store/calculation";
    @connect(
      state => ({ num: state }),
      { add, minus, asyncAdd }
    )
    
    class calculationNum extends Component {
      render() {
        return (
          <div>
            {this.props.num}
            <div>
              <button onClick={ () => this.props.add(2) }>+</button>
              <button onClick={ this.props.minus }>-</button>
            </div>
          </div>
        );
      }
    }
    

4. 高阶组件

  • 高阶组件是一个工厂函数,它接收一个组件返回另一个组件。返回的组件除了自己原有功能以外,还具有新的功能。
  • 举个例子:A组件原来只有展示的功能,经过B组件的“赋能”之后,除了原有的展示以外,还可以打印出log,这时候就需要用到高阶组件了。
    import React from "react";
    
    // 无状态组件Lesson,不关心逻辑,只关心展示
    function Lesson(props) {
      return (
        <div>
        	{ props.stage } - { props.title }
        </div>
      );
    }
    
    // 模拟数据
    const lessons = [
      { stage: "stage1", title: "title1" },
      { stage: "stage2", title: "title2" },
      { stage: "stage2", title: "title3" }
    ];
    
    // 接收数据并进行展示
    const withContent = Comp => props => {
      const content = lessons[props.idx];
      return <Comp {...content} />;
    };
    
    // 接收一个组件,保证组件在现有功能的基础上,打印出log
    const withLog = Comp => {
      return class extends React.Component {
        componentDidMount() {
          console.log('didMount', this.props);
        }
    
        render() {
          return <Comp {...this.props}></Comp>
        }
      }
    }
    
    // 装饰器语法 @withLog
    // 先后顺序:从下往上
    
    @withLog
    @withContent
    class Lesson2 extends React.Component {
      render() {
        return (
          <div>
            {this.props.stage} - {this.props.title}
          </div>
        );
      }
    }
    
    export default function test() {
      return (
        <div>
          {[0, 0, 0].map((item, idx) => (
            <Lesson2 key={idx} idx={idx} />
          ))}
        </div>
      );
    }
    

四. 总结

  • 以上这些是学习react组件的心得,如果可以掌握这些,对于日后项目组件代码的设计,解耦一定大有裨益。