如何创建React组件
有两种常见的方法:
React.Component
创建React组件的一种方法是创建ES6 class并进行扩展React.Component。使用此方法创建的每个组件都应该具有一个render函数,该函数返回在浏览器上呈现此组件时DOM的外观。
import React from 'react';
class Component extends React.Component {
//需要render函数
render() {
return <h1>Hello, 网页3剑客</h1>;
}
}
function
另一种创建React组件的常用方法是创建一个简单的函数,它接受一个参数(我们调用props)并返回与上面完全相同的东西 - 如果在浏览器上呈现此组件,DOM应该是什么样子。
function Component(props) {
return <h1>Hello, {props.name}</h1>;
}
注意:用户自定义的组件必须是首字母大写。React会将以小写字母开头的组件视为原生DOM标签。例如,<div />代表HTML的div标签,而<Component />则代表一个组件,并且需在作用域内使用Component。
如何创建React DOM
网页由DOM元素构成。React DOM 并不是浏览器的DOM,而是 React DOM只是用来告诉浏览器如何创建DOM的方法。通常情况下,我们并不需要React就能创建出一个DOM元素,但是React创建与管理DOM的方式有组件化、虚拟 DOM 等更高层次的抽象,由此带来的优势是更快的渲染速度,以及更好的维护性,因此值得去尝试。
JavaScript原生方法React.createElement
React.createElement是一个简单的javascript函数,它接受三个参数。第一个参数是要渲染的元素。第二个参数是我们想要传递给该元素的任何属性。第三个参数是此组件的子项。
import React from 'react';
function HelloWorld(props){
return (
React.createElement('div', null, 'Hello World')
);
}
在这个例子中,我们没有传递任何东西,所以它是null。
import React from 'react';
function HelloWorld(props){
return (
React.createElement('div', {className: "main"}, 'Hello World')
);
}
在这个例子中,div拥有main类名。
JSX语法
JSX 是一种 JavaScript 的语法糖。Facebook 开发JSX出来,主要用于 React 中。虽然 JSX 的内容会长得像 html,但还是 JavaScript。
import React from 'react';
function StockProfile(props) {
const stockTicker = 'APPL';
const companyProfileInfo = {
'Company Name': 'Apple Inc.',
'Price': 150,
'Exchange': "Nasdaq Global Select",
'Industry': "Computer Hardware",
'CEO': 'Timothy D. Cook'
}
return (
<div>
<div>Profile of: {stockTicker}</div>
<hr/>
<div>
{
Object.keys(companyProfileInfo)
.map((info, index) => {
return <div key={index}>{info} : {companyProfileInfo[info]}</div>
})
}
</div>
</div>
);
}
关键要点:
- 组件必须只返回一个标签。此标记可以包含任意数量的子项。但是,它可以返回字符串或null,而不是标记。
- 您可以在return使用花括号内运行任何Javascript代码{//run any Javascript}。
- return它之外的任何其他Javascript类或函数。你可以做任何你想做的事。
与HTML的差异
在JSX中有一些常用的东西与HTML略有不同。
style样式
在HTML中,样式作为字符串传递。css属性是kebab-cased。
<div style="bottom-border:1px solid green"></div>
在JSX中,样式作为对象传递。css属性是camelCased。
<div style={{ bottomBorder: `1px solid green`}}></div>
class类
在HTML类中,属性作为字符串传递。
<div class="container"></div>
在JSX中,class属性也作为字符串传递,但class我们称之为调用它而不是调用它className。那是因为JSX是Javascript的扩展,“class”是Javascript中的保留关键字。
<div className={"container"}></div>
事件处理程序
在HTML事件处理程序中,属性都是较低的,并且处理程序作为字符串传递。
<div onclick="clickHandler()"></div>
在JSX中,事件处理程序是camelCased而不是字符串,我们传递实际的函数。
<div onClick={function(){ alert('clicked')}}></div>
延伸:
在创建React DOM关键要点中说过组件必须只返回一个标签。也就是说在JSX中html代码第一层只能写一个元素。如果有多个标签(元素)并列,形成所谓的相邻JSX元素(adjacement jsx elements),就会报语法错误。如何突破JSX标签包裹的这种限制呢?目前有两种方法:
(1) 返回数组
如果的是数组,就没有问题。
// 突破JSX标签包裹限制1:返回数组
import React from 'react';
import ReactDOM from 'react-dom';
const arr = ['Adams', 'Bill', 'Charlie'];
const Arr = () => {
return arr.map((item, index) => {
return <p key={index}>{item}</p>
})
}
ReactDOM.render(<Arr />, document.getElementById('root'));
这里是一个数组 arr,包含三个名字,然后用 map 方法得到一个包含三段 JSX 代码的数组。注意这里需要写成匿名函数,然后以 <Arr /> 自封闭标签的格式放入 ReactDOM 的第一个参数位置去渲染。
当然,这段代码还可以进行简写return,自行尝试。
(2) 高阶组件(High Order Component, hoc)
div 去包裹并列元素的痛点是,我们可能并不需要这个多余的 div 标签,可能会破坏 html 结构,也许上层做了 flex,并不能有效的传递到这些并列标签上。
所以这里引入了用于辅助的高阶组件 hoc。虽然高阶组件的名字听起来很吓人,然而做的事情很简单,就是传递的作用。
// 突破JSX标签包裹限制:方法2 高阶组件
import React from 'react';
import ReactDOM from 'react-dom';
const Aux = props => props.children;
const title = (
<Aux>
<h1>Parallel elements demo</h1>
<p>Content</p>
</Aux>
);
ReactDOM.render(title, document.getElementById('root'));
在上面这段代码中,const Aux = props => props.children; 就是高阶组件。Aux 这个高阶组件的作用是把标签包括的内容进行传递和显示(Aux 是英文中的 auxiliary)。查看最终 html 结构会发现 div 已经消失了,而且代码没有 div 也能正常。
另外React 16.2 开始有一个所谓的 fragment 的做法,就是 React 自带了 <Aux></Aux>,但是写成 <></>。在 React 16.2,代码可以写成如下格式:
import React from 'react';
import ReactDOM from 'react-dom';
const title = (
<>
<h1>Parallel elements demo</h1>
<p>Content</p>
</>
);
ReactDOM.render(title, document.getElementById('root'));