首页 > 语言 > JavaScript > 正文

React 无状态组件(Stateless Component) 与高阶组件

2024-05-06 15:31:40
字体:
来源:转载
供稿:网友

无状态组件(Stateless Component) 是 React 0.14 之后推出的,大大增强了编写 React 组件的方便性,也提升了整体的渲染性能。

无状态组件 (Stateless Component)

function HelloComponent(props, /* context */) { return <div>Hello {props.name}</div>}ReactDOM.render(<HelloComponent name="Sebastian" />, mountNode)

HelloComponent 第一个参数是 props,第二个是 context。最后一句也可以这么写:

ReactDOM.render(HelloComponent{ name:"Sebastian" }, mountNode)

可以看到,原本需要写“类”定义(React.createClass 或者 class YourComponent extends React.Component)来创建自己组件的定义,现在被精简成了只写一个 render 函数。更值得一提的是,由于仅仅是一个无状态函数,React 在渲染的时候也省掉了将“组件类” 实例化的过程。

结合 ES6 的解构赋值,可以让代码更精简。例如下面这个 Input 组件:

function Input({ label, name, value, ...props }, { defaultTheme }) { const { theme, autoFocus, ...rootProps } = props return (  <label   htmlFor={name}   children={label || defaultLabel}   {...rootProps}  >  <input   name={name}   type="text"   value={value || ''}   theme={theme || defaultTheme}   {...props}  /> )}Input.contextTypes = {defaultTheme: React.PropTypes.object};

这个 Input 组件(仅仅是示例)直接实现了 label/inputText 的组合:

    defaultTheme 是从 Context 中解构出来的,如果 props 没有设定 theme,就将用 defaultTheme 替代。 autoFocus 需要被传递到底层的 inputText 而不能同时遗留给 label,因此会先通过 { theme, autoFocus, ...rootProps } = props 拿出来。

无状态组件用来实现 Server 端渲染也很方便,只要避免去直接访问各种 DOM 方法。

无状态组件与组件的生命周期方法

我们可以看到,无状态组件就剩了一个 render 方法,因此也就没有没法实现组件的生命周期方法,例如 componentDidMount, componentWillUnmount 等。那么如果需要让我们的 Input 组件能够响应窗口大小的变化,那么该如何实现呢?这其实还是要引入“有状态的组件”,只不过这个“有状态的组件”可以不仅仅为 "Input" 组件服务。

const ExecutionEnvironment = require('react/lib/ExecutionEnvironment')const defaultViewport = { width: 1366, height: 768 }; // Default size for server-side renderingfunction withViewport(ComposedComponent) { return class Viewport extends React.Component {  state = {   // Server 端渲染和单元测试的时候可未必有 DOM 存在   viewport: ExecutionEnvironment.canUseDOM ?     { width: window.innerWidth, height: window.innerHeight } : defaultViewport  }  componentDidMount() {   // Server 端渲染是不会执行到 `componentDidMount` 的,只会执行到 `componentWillMount`   window.addEventListener('resize', this.handleWindowResize)   window.addEventListener('orientationchange', this.handleWindowResize)  }  componentWillUnmount() {   window.removeEventListener('resize', this.handleWindowResize)   window.removeEventListener('orientationchange', this.handleWindowResize)  }  render() {   return <ComposedComponent {...this.props} viewport={this.state.viewport}/>  }  handleWindowResize() {   const { viewport } = this.state   if (viewport.width !== window.innerWidth || viewport.height !== window.innerHeight) {    this.setState({ viewport: { width: window.innerWidth, height: window.innerHeight } })   }    } }}            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选