组件化开发是React的核心,学会如何利用和组织他们有助于你创建良好的设计结构。
什么是组件?
根据react官网的解释大致如下:
组件可以独立的拆分你的UI试图,他们是可以复用的,独立的单元。
和函数类似,React中组件接收的输入源称为props,并且返回react元素。react元素是对UI界面的描述。你可以告诉react你期望的UI界面,剩下的工作可以交给react来处理。
我们拿乘坐计程车打比方,当你告诉司机你想要去的地方,司机就会按照你期望地点将你安全的送到目的地。而不用你自己亲自开车。
Component Api's
react的api有哪些呢?react总共有主要的5大api他们分别是:
1.render
2.state
3.props
4.context
5.life cycle events
组件有状态组件和无状态组件,状态组件使用可控制状态的api,render state 和life cycle events。无状态组件使用render props context。
组件设计模式,可以将你的数据层和逻辑层分开,通过职责区分你的组件。你可以创建可以复用的组件,而这些组件又可以创建出更加复杂的UI试图。这对于构建app是极为重要的。
在组件设计模式中我们可以将组件分为:
1.容器组件
2.展示型组件
3.高阶组件
4.render回调
容器组件:
容器组件用于获取数据,渲染他下面的子组件,这个就是容器组件。
容器组件可以是你的数据层或者业务逻辑层,并且使用的是stateful api。通过生命周期函数你可以连接你的状态管理库,例如redux或者flux。容器组件可以传递数据和回调函数给子组件。在容器组件的render方法中,通过展示组件的组合来构建你的UI试图。因为容器组件是具有状态的,所以你需要使用class来声明你的组件,而不是使用函数式组件。
在如下例子中,有个class component名为Greeting,他有state,生命周期函数和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> ); } }
这个组件是具备状态的class组件。为了让Greeting组件成为容器型组件,我们需要把UI拆分到展示型组件中。如下:
展示型组件:
展示型组件利用的是,props,render,context(stateless api's)
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> ); } }
如上示例,我们移除了标签元素,并且将他放入了无状态的展示型组件中。当然这个只是这个很简单的示例,但是在复杂的app运用中,原理都是相同的。
高阶组件:
高阶组件,是以组件作为参数,并且返回一个新的组件。
高阶组件可以提供数据给任意数量的组件,并且有效的复用业务逻辑。它是个强大的模式。例如在react-router和redux中,在react-router中你可以使用widthRouter()去继承方法,并且通过props传递给你的组件。在redux中你可以connect方法去传递你的actions。
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);
如上示例,我们通过this.props.location.pathname来更新状态。通过withRouter方法来包裹组件。现在我们的组件可以通过props来出来react-rouoter的方法this.props.location.pathname;
Render callbacks
类似于高阶组件,render callbacks或者render props都是用来复用组价逻辑的。当更多的开发者倾向于高阶组件来复用业务逻辑的时候,这里有几个原因和优点可以让你尝试下使用render callbacks。render callsbacks可以有效的减少命名冲突,并且清晰的展示逻辑的来源。
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中的state。
原文出处:https://www.cnblogs.com/chargo/p/9471026.html