在初学 React 的时刻,分不清 React 组件和 React 元素,实在踩了一些坑。搞清晰 React 中什么是组件,什么是元素,既能够理清晰观点,也能够让你防止一些不必要的毛病。
React 元素
React 元素(React element),它是 React 中最小基本单位,我们能够运用 JSX 语法轻松地建立一个 React 元素:
const element = <div className="element">I'm element</div>
React 元素不是实在的 DOM 元素,它仅仅是 js 的平常对象(plain objects),所以也没办法直接挪用 DOM 原生的 API。上面的 JSX 转译后的对象大概是如许的:
{
_context: Object,
_owner: null,
key: null,
props: {
className: 'element',
children: 'I'm element'
},
ref: null,
type: "div"
}
只要在这个元素衬着被完成后,才经由过程选择器的体式格局猎取它对应的 DOM 元素。不过,根据 React 有限状况机的设想头脑,应当运用状况和属性来表述组件,要只管防止 DOM 操纵,即便要举行 DOM 操纵,也应当运用 React 供应的接口ref
和getDOMNode()
。平常运用 React 供应的接口就足以敷衍须要 DOM 操纵的场景了,因而像 jQuery 壮大的选择器在 React 中几乎没有用武之地了。
除了运用 JSX 语法,我们还能够运用 React.createElement()
和 React.cloneElement()
来构建 React 元素。
React.createElement()
JSX 语法就是用React.createElement()
来构建 React 元素的。它接收三个参数,第一个参数能够是一个标署名。如div
、span
,或许 React 组件。第二个参数为传入的属性。第三个以及以后的参数,皆作为组件的子组件。
React.createElement(
type,
[props],
[...children]
)
React.cloneElement()
React.cloneElement()
与React.createElement()
类似,差别的是它传入的第一个参数是一个 React 元素,而不是标署名或组件。新增加的属性会并入原有的属性,传入到返回的新元素中,而就的子元素奖杯替代。
React.cloneElement(
element,
[props],
[...children]
)
React 组件
React 中有三种构建组件的体式格局。React.createClass()
、ES6 class
和无状况函数。
React.createClass()
React.createClass()
是三种体式格局中最早,兼容性最好的要领。在0.14版本前官方指定的组件写法。
var Greeting = React.createClass({
render: function() {
return <h1>Hello, {this.props.name}</h1>;
}
});
ES6 class
ES6 class
是现在官方引荐的运用体式格局,它运用了ES6规范语法来构建,但它的完成还是挪用React.createClass()
来完成了,ES6 class
的生命周期和自动绑定体式格局与React.createClass()
略有差别。
class Greeting extemds React.Component{
render: function() {
return <h1>Hello, {this.props.name}</h1>;
}
};
无状况函数
无状况函数是运用函数构建的无状况组件,无状况组件传入props
和context
两个参数,它没有state
,除了render()
,没有别的生命周期要领。
function Greeting (props) {
return <h1>Hello, {props.name}</h1>;
}
React.createClass()
和ES6 class
构建的组件的数据结构是类,无状况组件数据结构是函数,它们在 React 被视为是一样的。
元素与组件的区分
组件是由元素组成的。元素数据结构是平常对象,而组件数据结构是类或纯函数。除此之外,另有几点区分要注意:
this.props.children
在 JSX 中,被元素嵌套的元素会以属性 children 的体式格局传入该元素的组件。当仅嵌套一个元素时,children 是一个 React 元素,当嵌套多个元素时,children 是一个 React 元素的数组。能够直接把 children 写入 JSX 的中,但假如要给它们传入新属性,就要用到React.cloneElement()
来构建新的元素。我曾放过以下毛病:
render () {
var Child = this.props.children
return <div><Child tip={'error!'}/><div>
}
由于 Child 是一个 React 元素,而不是组件,如许的写法是完整毛病的,准确的体式格局应当是:
render () {
var child = this.props.children
return <div>{ React.cloneElement(child, {tip: 'right way!'}) }<div>
}
就如许,原有属性和新增加的属性被一并传入了子元素。运用React.cloneElement()
才是操纵元素的准确姿态。
用户组件
有的时刻,组件能够让用户以属性的体式格局传入自定义的组件,来提拔组件的灵活性。这个属性传入的就应当是 React 元素,而非 React 组件。运用 React 元素能够让用户传入自定义组件的同时,为组件增加属性。一样,能够运用React.cloneElement()
为自定义组件增加更多属性,或替代子元素。
// 引荐
<MyComponent tick={
<UserComponent tip="Yes"/>
} />
// 不引荐
<MyComponent tick={ UserComponent } />
末了
末了,打个不适当的比方,React 组件是MyComponent
,React 元素就是<MyComponent />
。