想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!前端
组件是 React 的核心,所以了解如何利用它们对于建立优秀的设计结构相当重要。react
根据 React 官网的介绍,“组件让你能够将 UI 分割成独立的、可重用的部分,并独立管理每一个部分。”git
当你第一次安装 npm install react
时,会获得一件事:组件及其 API。与 JavaScript 函数相似,组件接受名为 “props” 的输入并返回 React 元素,该元素描述(声明)用户界面(UI)的外观。这就是为何 React 被称为声明性 API,由于你告诉它你但愿 UI 是什么样子的,而 React 负责其他的工做。github
能够把声明式想像成当打的去一个目的地时,只须要告诉司机去哪里,他就会开车把你送到那里。命令式编程正好相反—,你得本身驾车到那里。npm
当安装 React 后,即可以使用 React 提供的 API,基本能够分红 5 种。编程
尽管一个组件可使用上述全部 API,但一个组件一般用到只有少数几个 API,而其余组件则只使用其余 API。redux
能够对组件使用不一样的 API 对组件进行划分,分为 有状态(stateful) 和 无状态(stateless) 两种组件。segmentfault
以上就是咱们为佬要介绍 组件模式 的缘由。组件模式是使用 React 时的最佳实践,最初引入组件模式是为了将数据逻辑和 UI 表现层进行分离。经过在组件之间划分职责,您以建立更多可重用的、内聚的组件,这些组件可用于组合复杂的 UI,这在构建可扩展的应用程序时尤为重要。react-router
一般组件模式有如下几种:less
“容器组件就是取数据,而后渲染子组件而已” —— Jason Bonta
容器组件是你的数据或逻辑层并利用 stateful API,使用生命周期事件,你能够链接 state
到 redux
或者 Flux
的 storage
中,并将数据和回调做为 props
传递给子组件。
在容器组件的 render
方法中,你可使用 展现组件 来渲染具体的样式。为了可以访问到全部状态 API,容器组件必须使用 class
的方式声明,而不是使用函数式方法声明。
在下面的示例中,咱们有一个名为 Greeting
的类组件,它具备状态,生命周期事件componentDidMount()
和 render
方法。
class Greeting extends React.Component { constructor() { super(); this.state = { name: "", }; } componentDidMount() { // AJAX this.setState(() => { return { name: "William", }; }); } render() { return ( <div> <h1>Hello! {this.state.name}</h1> </div> ); } }
此时,该组件是一个有状态类组件,为了使 Greeting
成为一个容器组件,咱们能够将 UI 拆分为一个 展现组件,将在下面进行说明。
展现组件 使用 props
、render
和 context
(无状态API),而且因为不须要使用生命周期相关 Api,可使用纯函数来简化表述它们:
const GreetingCard = (props) => { return ( <div> <h1>Hello! {props.name}</h1> </div> ) }
展现组件 仅从 props
接收数据和回调,这些数据和回调能够由其容器组件(父组件)提供。
容器组件和展现组件各自将数据/逻辑和展现部分封装到各自的组件中:
const GreetingCard = (props) => { return ( <div> <h1>{props.name}</h1> </div> ) } class Greeting extends React.Component { constructor() { super(); this.state = { name: "", }; } componentDidMount() { // AJAX this.setState(() => { return { name: "William", }; }); } render() { return ( <div> <GreetingCard name={this.state.name} /> </div> ); } }
如你所见,已经将 Greeting
组件中展现相关的部分移动到了它本身的函数式展现组件中。固然,这是一个很是简单的例子——对于更复杂的应用程序,这也是最基本的。
高阶组件是一种函数,它接受一个组件做为参数,而后返回一个新的组件。
这是一种能够对输入组件的 props
进行修改(增删改查)而后返回全新的修改后的组件强大模式,想一想 react-router-v4 和 redux 。用了 react-router-v4 后,你可使用 withRouter() 来继承以 props
形式传递给组件的各类方法。一样,用了redux
,就可使用 connect({})()
方法来将展现组件和 store
中的数据进行链接。
代码演示:
import {withRouter} from 'react-router-dom'; class App extends React.Component { constructor() { super(); this.state = {path: ''} } componentDidMount() { let pathName = this.props.location.pathname; this.setState(() => { return { path: pathName, } }) } render() { return ( <div> <h1>Hi! I'm being rendered at: {this.state.path}</h1> </div> ) } } export default withRouter(App);
导出组件时,使用用 react-router-v4 的 withRouter()
方法封装它。 在 组件 App 的生命周期事件 componentDidMount()
方法中,咱们使用this.props.location.pathname
提供的值来更新 state
。 因为咱们使用了 withRouter
高阶组件,咱们能够直接访问 this.props.locationlocation
,而不须要直接将 location
做为 props
直接传入,很是方便。
与高阶组件相似,渲染回调或渲染 props
被用于共享或重用组件逻辑。虽然许多开发人员倾向于使用 高阶组件 的可重用逻辑,可是使用 渲染回调 仍然有一些很是好的理由和优点——这是在 Michael Jackson 的“永不写另外一个高阶组件”中获得了最好的解释。简而言之,渲染回调减小了命名空间冲突,并更好的说明了逻辑来源。
class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 0, }; } increment = () => { this.setState(prevState => { return { count: prevState.count + 1, }; }); }; render() { return ( <div onClick={this.increment}>{this.props.children(this.state)}</div> ); } } class App extends React.Component { render() { return ( <Counter> {state => ( <div> <h1>The count is: {state.count}</h1> </div> )} </Counter> ); } }
在 Counter
类中,在 render
方法中嵌入 this.props.children
并将 this.state
做为参数。在 App
类中,咱们能够将咱们组件封装在 Counter
组件中,所以我能够操做 Counter
组件内的逻辑。
Counter
组件的本质是暴露了 children
这个外部属性,将 children
具体的渲染细节交个 Counter
的使用者,使用的时候只须要将组件传入到 Counter
的 children
中,固然可使用其余参数,若是 children
不够的话。
代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug。
原文:
https://medium.com/teamsubcha...
你的点赞是我持续分享好东西的动力,欢迎点赞!