React学习:组件(Components)

React :元素构成组件(复杂的组件由多个组件构成),组件又构成应用。
React核心思想是组件化,其中 组件 通过属性(props) 和 状态(state)传递数据。


一、什么是组件?

React通过组件的思想,将界面拆分成一个个可复用的模块,每一个模块就是一个React 组件。一个React 应用由若干组件组合而成,一个复杂组件也可以由若干简单组件组合而成。

React 组件可以用好几种方式声明,可以是一个包含 render() 方法的类,也可以是一个简单的函数,不管怎么样,它都是以props作为输入,返回 React 元素作为输出。


二、组件的作用

React组件最核心的作用是返回React元素。

这里你也许会问:React元素不应该是由React.createElement() 返回的吗?
其实React组件就是调用React.createElement(),返回React元素,供React内部将其渲染成最终的页面DOM。

下面看两种创建组件的方式:

//函数式
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
//类定义
class Welcome extends React.Component {
    //render函数并不做实际的渲染动作,他只是返回一个JSX
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

无论是函数式组件,还是类定义组件,最终组件return的都是React元素,而return的React元素(JSX)则又调用了 React.createElement()

从return React元素到组件被实际渲染 挂到DOM树上 中间还有很复杂的过程。
比如:在类组件中render函数被调用完之后,componentDidMount函数并不是会被立刻调用。componentDidMount被调用的时候,render函数返回的东西已经引发了渲染,组件已经被『装载』到了DOM树上

其实,使用类定义的组件,render方法是唯一必需的方法,其他组件的生命周期方法都只不过是为render服务而已,都不是必需的。


三、创建组件

组件是由元素构成的。元素数据结构是普通对象,而组件数据结构是类或纯函数。

React 中有三种构建组件的方式:

  • 类 组件:class extends React.Component()
  • js函数式组件
  • React.createClass()

1、类 组件
相比于函数式组件功能更强大。它有state,以及不同的生命周期方法,可以让开发者能够在组件的不同阶段(挂载、更新、卸载),对组件做更多的控制。
类组件可能是无状态组件,也可能是有状态组件。详见:组件分类

//组件名首字母必须大写
class Welcome extends React.Component{
  //添加其他事件函数这么加:myWay(){···}
  render(){
    return (<div>my name is {this.props.name},{this.props.age}</div>);
  }
};

2、函数式组件
JavaScript 函数构建的组件一定是无状态组件。它能传入props和context两个参数,没有state,除了render(),没有其它生命周期方法。
但正是这样,函数组件才更加专注和单一,它只是一个返回React 元素的函数,只关注对应UI的展现。函数组件接收外部传入的props,返回对应UI的DOM描述。

//组件名称总是以大写字母开始。
//定义模版的函数名首字母必须大写
function Welcome(props){
  //添加其他事件函数这么加:function otherFun(){·····}
  return <div>my name is {props.name},{props.age}</div>;
}

3、React.createClass()

/*组件首字母必须大写,eg:Greeting的G*/
var Greeting = React.createClass({
  render: function() {
    return <h1>Hello, {this.props.name}</h1>;
  }
});

创建组件时需注意:
1、给组件命名时,组件首字母必须大写
2、render()方法的return 里,只能有一个html父标签,所以涉及到多个html标签时,必须外面再嵌套个父标签


四、渲染一个组件

1、类 组件

//组件名首字母必须大写
class Welcome extends React.Component{
  render(){
    return (<div>my name is {this.props.name},{this.props.age}</div>);
  }
};
//const element必须在定义组件之后
const element = (
  <Welcome name='bty' age="12"/>
);
ReactDOM.render(
  element,
  document.getElementById('root')
);

输出:my name is bty,12

2、js函数式组件

function Welcome(props){
  return <div>my name is {props.name},{props.age}</div>;
}
const element = (
  <Welcome name='bty' age='12'/>
);
ReactDOM.render(
  element,
  document.getElementById('root')
);

输出:同上

工作步骤:
(1) 调用ReactDOM.render(),并向其中传入
< Welcome name=’bty’ age=’12’/>元素。
(2) React 调用 Welcome 组件,并向其中传入了 {name: ‘bty’,age=’12’} 作为 props 对象
(3) Welcome 组件返回 < div>my name is {props.name},{props.age}
(4) React DOM 迅速更新 DOM ,使其显示为 < div>my name is bty,12


五、组件嵌套

function Myhi(props){
   return <h1>I‘m {props.name}</h1>
}
class Welcome extends React.Component{
  render(){
    return(
      <div>
        <p>start</p>
        <Myhi name="bty"/>
        <Myhi name="ssh"/>
        <Myhi name="mama"/>
      </div>)    
  }
};
ReactDOM.render(
  <Welcome/>,
  document.getElementById('root')
);

输出:
start
I‘m bty
I‘m ssh
I‘m mama

组件嵌套是如何渲染的?
拿上面例子说,
(1)首先调用ReactDOM.render(),向其中传入< Welcome/>组件;
(2)渲染时:组件< Welcome/>知道如何渲染< p>标签,但不知道如何渲染< Myhi/>,所以再继续调用解析对应组件< Myhi/>,并以{name:'···'}作为props对象传给Myhi组件,返回React 元素
(3)像上面这样一直做递归,直到返回的React 元素中只包含DOM节点为止

这样React 就能获取到页面的完整DOM结构信息,渲染的工作自然就ok了。


六、组件的实例

React 组件是一个函数或类,实际工作时,发挥作用的是React 组件的实例对象。只有组件实例化后,每一个组件实例才有了自己的props和state,才持有对它的DOM节点和子组件实例的引用。
传统的面向对象的开发方式中,实例化的工作是由开发者自己手动完成的,但在React中,组件的实例化工作是由React自动完成的,组件实例也是直接由React管理的。换句话说,开发者完全不必关心组件实例的创建、更新和销毁。

在类组件中 的实例,就是用 this 引用的那个对象,对于保存本地状态以及介入生命周期函数是有用的。


注:组件必须是 纯函数

无论你用函数或类的方法来声明组件, 它都无法修改其自身 props. 思考下列 sum (求和)函数:

function sum(a, b) {
  return a + b;
}

这种函数称为 “纯函数” ,因为它们不会试图改变它们的输入,并且对于同样的输入,始终可以得到相同的结果。

反之, 以下是非纯函数, 因为它改变了自身的输入值:

function withdraw(account, amount) {
  account.total -= amount;
}

严格的规则:
所有 React 组件都必须是纯函数,并禁止修改其自身 props

猜你喜欢

转载自blog.csdn.net/b954960630/article/details/79814331