组件的各种概念解析

1.类组件

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}
// 注意: props只读

 

2.函数组件

function Welcome(props) { // 组件名首字母必须大些
  return <h1>Hello, {props.name}</h1>; // Props只读
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

// 1.我们对<Welcome name="Sara" />元素调用了ReactDOM.render()方法。
// 2.React将{name: 'Sara'}作为props传入并调用Welcome组件。
// 3.Welcome组件将<h1>Hello, Sara</h1>元素作为结果返回。
// 4.React DOM将DOM更新为<h1>Hello, Sara</h1>。

  函数组件和类组件是将props属性转变成UI

  高阶组件则是将一个组件转换成另一个组件

3.高阶组件

   高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。

   高阶组件就是一个没有副作用的纯函数。

  不要改变原始组件,使用组合

   例如:Redux的connect方法

// This function takes a component...
function withSubscription(WrappedComponent, selectData) {
  // ...and returns another component...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // ... that takes care of the subscription...
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ... and renders the wrapped component with the fresh data!
      // Notice that we pass through any additional props
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

约定:贯穿传递不相关props属性给被包裹的组件

render() {
  // 过滤掉专用于这个阶组件的props属性,
  // 不应该被贯穿传递
  const { extraProp, ...passThroughProps } = this.props;

  // 向被包裹的组件注入props属性,这些一般都是状态值或
  // 实例方法
  const injectedProp = someStateOrInstanceMethod;

  // 向被包裹的组件传递props属性
  return (
    <WrappedComponent
      injectedProp={injectedProp}
      {...passThroughProps}
    />
  );
}

 

约定:最大化的组合性

// 不要这样做……
const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent))

// ……你可以使用一个函数组合工具
// compose(f, g, h) 和 (...args) => f(g(h(...args)))是一样的
const enhance = compose(
  // 这些都是单独一个参数的高阶组件
  withRouter,
  connect(commentSelector)
)
const EnhancedComponent = enhance(WrappedComponent)

单独一个参数的高阶组件,类似 connect 函数返回的,签名是Component => Component。输入和输出类型相同的函数确实是很容易组合在一起。

约定:包装显示名字以便于调试

function withSubscription(WrappedComponent) {
  class WithSubscription extends React.Component {/* ... */}
  WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;
  return WithSubscription;
}

function getDisplayName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

React Developer Tools便于调试,

 

注意:

不要在render方法内使用高阶组件

原因: (差分算法,渲染性能问题)

render() {
  // 每一次渲染,都会创建一个新的EnhancedComponent版本
  // EnhancedComponent1 !== EnhancedComponent2
  const EnhancedComponent = enhance(MyComponent);
  // 那引起每一次都会使子对象树完全被卸载/重新加载
  return <EnhancedComponent />;
}

必须将静态方法做拷贝

 1)可借助hoist-non-react-statics

function enhance(WrappedComponent) {
  class Enhance extends React.Component {/*...*/}
  // 必须得知道要拷贝的方法 :(
  Enhance.staticMethod = WrappedComponent.staticMethod;
  return Enhance;
}

2)分别导出组件自身的静态方法。

// Instead of...
MyComponent.someFunction = someFunction;
export default MyComponent;

// ...export the method separately...
export { someFunction };

// ...and in the consuming module, import both
import MyComponent, { someFunction } from './MyComponent.js';

Refs属性不能贯穿传递

如果你向一个由高阶组件创建的组件的元素添加ref应用,那么ref指向的是最外层容器组件实例的,而不是被包裹的组件。

现在我们提供一个名为 React.forwardRef 的 API 来解决这一问题(在 React 16.3 版本中)

转载于:https://www.cnblogs.com/lyraLee/p/10510810.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值