元素渲染
将一个元素渲染为 DOM
假设你的 HTML 文件某处有一个 <div>:
<div id="root"></div>
我们将其称为“根” DOM 节点,因为该节点内的所有内容都将由 React DOM 管理。
仅使用 React 构建的应用通常只有单一的根 DOM 节点。如果你在将 React 集成进一个已有应用,那么你可以在应用中包含任意多的独立根 DOM 节点。
想要将一个 React 元素渲染到根 DOM 节点中,只需把它们一起传入 ReactDOM.render():
const element = <h1>Hello, world</h1>;ReactDOM.render(element, document.getElementById('root'));
更新已渲染的元素
考虑一个计时器的例子:
function tick() {const element = (<div><h1>Hello, world!</h1><h2>It is {new Date().toLocaleTimeString()}.</h2></div>);ReactDOM.render(element, document.getElementById('root'));}setInterval(tick, 1000);
这个例子会在 setInterval() 回调函数,每秒都调用 ReactDOM.render()。
组件&Props
函数组件与 class 组件
定义组件最简单的方式就是编写 JavaScript 函数:
function Welcome(props) {return <h1>Hello, {props.name}</h1>;}
你同时还可以使用 ES6 的 class 来定义组件:
class Welcome extends React.Component {render() {return <h1>Hello, {this.props.name}</h1>;}}
渲染组件
function Welcome(props) {return <h1>Hello, {props.name}</h1>;}const element = <Welcome name="Sara" />;ReactDOM.render(element,document.getElementById('root'));
组合组件
function Welcome(props) {return <h1>Hello, {props.name}</h1>;}function App() {return (<div><Welcome name="Sara" /><Welcome name="Cahal" /><Welcome name="Edite" /></div>);}ReactDOM.render(<App />,document.getElementById('root'));
提取组件
function Comment(props) {return (<div className="Comment"><div className="UserInfo"><img className="Avatar"src={props.author.avatarUrl}alt={props.author.name}/><div className="UserInfo-name">{props.author.name}</div></div><div className="Comment-text">{props.text}</div><div className="Comment-date">{formatDate(props.date)}</div></div>);}
该组件用于描述一个社交媒体网站上的评论功能,它接收 author(对象),text (字符串)以及 date(日期)作为 props。
该组件由于嵌套的关系,变得难以维护,且很难复用它的各个部分。因此,让我们从中提取一些组件出来。
首先,我们将提取 Avatar 组件:
function Avatar(props) {return (<img className="Avatar"src={props.user.avatarUrl}alt={props.user.name}/>);}
Avatar 不需知道它在 Comment 组件内部是如何渲染的。因此,我们给它的 props 起了一个更通用的名字:user,而不是 author。
我们建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。
我们现在针对 Comment 做些微小调整:
function Comment(props) {return (<div className="Comment"><div className="UserInfo"><Avatar user={props.author} /><div className="UserInfo-name">{props.author.name}</div></div><div className="Comment-text">{props.text}</div><div className="Comment-date">{formatDate(props.date)}</div></div>);}
接下来,我们将提取 UserInfo 组件,该组件在用户名旁渲染 Avatar 组件:
function UserInfo(props) {return (<div className="UserInfo"><Avatar user={props.user} /><div className="UserInfo-name">{props.user.name}</div></div>);}
进一步简化 Comment 组件:
function Comment(props) {return (<div className="Comment"><UserInfo user={props.author} /><div className="Comment-text">{props.text}</div><div className="Comment-date">{formatDate(props.date)}</div></div>);}
组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props。来看下这个 sum 函数:
function sum(a, b) {return a + b;}
这样的函数被称为“纯函数”
相反,下面这个函数则不是纯函数,因为它更改了自己的入参:
function withdraw(account, amount) {account.total -= amount;}
React 非常灵活,但它也有一个严格的规则:
所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
