欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈React中的元素、组件、实例和节点

程序员文章站 2022-03-20 15:01:22
react 深入系列,深入讲解了react中的重点概念、特性和模式等,旨在帮助大家加深对react的理解,以及在项目中更加灵活地使用react。 react 中的元素...

react 深入系列,深入讲解了react中的重点概念、特性和模式等,旨在帮助大家加深对react的理解,以及在项目中更加灵活地使用react。

react 中的元素、组件、实例和节点,是react中关系密切的4个概念,也是很容易让react 初学者迷惑的4个概念。现在,老*就来详细地介绍这4个概念,以及它们之间的联系和区别,满足喜欢咬文嚼字、刨根问底的同学(老*就是其中一员)的好奇心。

元素 (element)

react 元素其实就是一个简单javascript对象,一个react 元素和界面上的一部分dom对应,描述了这部分dom的结构及渲染效果。一般我们通过jsx语法创建react 元素,例如:

const element = <h1 classname='greeting'>hello, world</h1>;

element是一个react 元素。在编译环节,jsx 语法会被编译成对react.createelement()的调用,从这个函数名上也可以看出,jsx语法返回的是一个react 元素。上面的例子编译后的结果为:

const element = react.createelement(
 'h1',
 {classname: 'greeting'},
 'hello, world!'
);

最终,element的值是类似下面的一个简单javascript对象:

const element = {
 type: 'h1',
 props: {
  classname: 'greeting',
  children: 'hello, world'
 }
}

react 元素可以分为两类:dom类型的元素和组件类型的元素。dom类型的元素使用像h1、div、p等dom节点创建react 元素,前面的例子就是一个dom类型的元素;组件类型的元素使用react 组件创建react 元素,例如:

const buttonelement = <button color='red'>ok</button>;

buttonelement就是一个组件类型的元素,它的值是:

const buttonelement = {
 type: 'button',
 props: {
  color: 'red',
  children: 'ok'
 }
}

对于dom类型的元素,因为和页面的dom节点直接对应,所以react知道如何进行渲染。但是对于组件类型的元素,如buttonelement,react是无法直接知道应该把buttonelement渲染成哪种结构的页面dom,这时就需要组件自身提供react能够识别的dom节点信息,具体实现方式在介绍组件时会详细介绍。

有了react 元素,我们应该如何使用它呢?其实,绝大多数情况下,我们都不会直接使用react 元素,react 内部会自动根据react 元素,渲染出最终的页面dom。更确切地说,react元素描述的是react虚拟dom的结构,react会根据虚拟dom渲染出页面的真实dom。

组件 (component)

react 组件,应该是大家最熟悉的react中的概念。react通过组件的思想,将界面拆分成一个个可以复用的模块,每一个模块就是一个react 组件。一个react 应用由若干组件组合而成,一个复杂组件也可以由若干简单组件组合而成。

react组件和react元素关系密切,react组件最核心的作用是返回react元素。这里你也许会有疑问:react元素不应该是由react.createelement() 返回的吗?但react.createelement()的调用本身也是需要有“人”负责的,react组件正是这个“责任人”。react组件负责调用react.createelement(),返回react元素,供react内部将其渲染成最终的页面dom。

既然组件的核心作用是返回react元素,那么最简单的组件就是一个返回react元素的函数:

function welcome(props) {
 return <h1>hello, {props.name}</h1>;
}

welcome是一个用函数定义的组件。如果使用类(class)定义组件,返回react元素的工作具体就由组件的render方法承担,例如:

class welcome extends react.component {
 render() {
  return <h1>hello, {this.props.name}</h1>;
 }
}

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

现在来考虑下面这个例子:

class home extends react.component {
 render() {
  return (
   <div>
    <welcome name='老*' />
    <p>anything you like</p>
   </div>
  )
 }
}

home 组件使用了welcome组件,返回的react元素为:

{
 type: 'div',
 props: {
  children: [
   {
    type: 'welcome',
    props: {
     name: '老*'
    }
   },
   {
    type: 'p',
    props: {
     children: 'anything you like'
    }
   },
  ]
 }
}

对于这个结构,react 知道如何渲染type = 'div' 和 type = 'p' 的节点,但不知道如何渲染type='welcome'的节点,当react 发现welcome 是一个react 组件时(判断依据是welcome首字母为大写),会根据welcome组件返回的react 元素决定如何渲染welcome节点。welcome组件返回的react 元素为:

{
 type: 'h1',
 props: {
  children: 'hello, 老*'
 }
}

这个结构中只包含dom节点,react是知道如何渲染的。如果这个结构中还包含其他组件节点,react 会重复上面的过程,继续解析对应组件返回的react 元素,直到返回的react 元素中只包含dom节点为止。这样的递归过程,让react 获取到页面的完整dom结构信息,渲染的工作自然就水到渠成了。

另外,如果仔细思考的话,可以发现,react 组件的复用,本质上是为了复用这个组件返回的react 元素,react 元素是react 应用的最基础组成单位。

实例 (instance)

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

节点 (node)

在使用proptypes校验组件属性时,有这样一种类型:

mycomponent.proptypes = { 
 optionalnode: proptypes.node,
}

proptypes.node又是什么类型呢?这表明optionalnode是一个react 节点。react 节点是指可以被react渲染的数据类型,包括数字、字符串、react 元素,或者是一个包含这些类型数据的数组。例如:

// 数字类型的节点
function mycomponent(props) {
 return 1;
}

// 字符串类型的节点
function mycomponent(props) {
 return 'mycomponent';
}

// react元素类型的节点
function mycomponent(props) {
 return <div>react element</div>;
}

// 数组类型的节点,数组的元素只能是其他合法的react节点
function mycomponent(props) {
 const element = <div>react element</div>;
 const arr = [1, 'mycomponent', element];
 return arr;
}

// 错误,不是合法的react节点
function mycomponent(props) {
 const obj = { a : 1}
 return obj;
}

最后总结一下,react 元素和组件的概念最重要,也最容易混淆;react 组件实例的概念大家了解即可,几乎使用不到;react 节点有一定使用场景,但看过本文后应该也就不存在理解问题了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。