元素渲染
02. 元素渲染元素是构成 React 应用的最小砖块,描述了你在屏幕上想看到的内容。
1const element = <h1>Hello, world</h1>;
与浏览器的 DOM 元素不同,React 元素是创建开销极小的普通对象。React DOM 会负责更新 DOM 来与 React 元素保持一致。
将一个元素渲染为 DOM假设你的 HTML 文件某处有一个 <div>:
1<div id="root"></div>
根节点,React应用只有单一根DOM节点
但一个html页面可以有多个React应用,每个应用对应一个独立根节点。
12const el = <h1>Hello</h1>ReactDOM.render(el, document.getElementById('root'))
更新已渲染的元素React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。一个元素就像电影的单帧:它代表了某个特定时刻的 UI。
根 ...
State&生命周期
04. State & 生命周期State 与 props 类似,但是 state 是私有的,并且完全受控于当前组件.
State类似于vue中的data选项
将函数组件转换成 class 组件
在没有useState钩子函数之前,是通过class组件管理State ?
12345678910class Clock extends React.Component { render() { return ( <div> <h1>Hello, world</h1> <h2>It is {this.props.date.toLocalTimeString()}</h2> </div> ) }}
每次组件更新时 render 方法都会被调用,但只要在相同的 DOM 节点中渲染 <Clock /> ,就仅有一个 Clock 组件的 class 实例被创建使用。这就使得我们可以使用 ...
组件&Props
03. 组件 & Props函数组件与 class 组件1.函数组件123function Welcome(props){ return <h1>Hello, {props.name}</h1>}
该函数是一个有效的React组件。接收唯一带有数据的props参数,并返回一个React元素。
2.class组件使用ES6的class来定义:
123456class Welcome extends React.Component{ // render 方法描述你想在屏幕看到的内容 render() { return <h1>Hello, {this.props.name}</h1> }}
以上两个组件是等效的。
函数组件与Class组件在事件处理上的一些区别
使用class组件时的事件处理: onClick={() => this.props.onClick()}
使用函数组件时的事件处 ...
事件处理
05. 事件处理与传统HTML绑定事件的区别传统的 HTML:
123<button onclick="activateLasers()"> Activate Lasers</button>
在 React 中略微不同:
1234// 1.事件名为小驼峰; 2.传入函数以大括号包裹函数名形式<button onClick={activateLasers}> Activate Lasers</button>
React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
阻止默认事件 (合成事件对象)在 React 中,你需要这样阻止默认事件:
123456789101112function ActionLink() { function handleClick(e) { e.preventDefault(); console.log('The link was ...
条件渲染
06. 条件渲染React 中的条件渲染和 JavaScript 中的一样,使用 JavaScript 运算符 if 或者条件运算符去创建元素来表现当前的状态,然后让 React 根据它们来更新 UI。
观察这两个组件:
1234567function UserGreeting(props) { return <h1>Welcome back!</h1>;}function GuestGreeting(props) { return <h1>Please sign up.</h1>;}
再创建一个 Greeting 组件,它会根据用户是否登录来决定显示上面的哪一个组件。
123456789101112131415function Greeting(props) { const isLoggedIn = props.isLoggedIn; // 根据条件来渲染组件(UI) if (isLoggedIn) { return <UserGreeting /& ...
列表&Key
07. 列表 & Key如下代码,我们使用 map() 函数让数组中的每一项变双倍,然后我们得到了一个新的列表 doubled 并打印出来:
123const numbers = [1, 2, 3, 4, 5];const doubled = numbers.map((number) => number * 2);console.log(doubled);
在 React 中,把数组转化为元素列表的过程是相似的。
渲染多个组件12345678910const numbers = [1,2,3]// 通过map方法将数值放入li,形成一个li标签组成的数值,在一次性放入ulconst listItems = numbers.map(number => { <li>{numbers}</li>})ReactDOM.render( <ul>{listItems}</ul> document.getElementById('root'))
...
表单
08. 表单受控组件(双向数据绑定)在 HTML 中,表单元素(如<input>、 <textarea> 和 <select>)通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。
我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
例如,如果我们想让前一个示例在提交时打印出名称,我们可以将表单写为受控组件:
123456789101112131415161718192021222324252627282930class Name extends React.Component { constructor(props){ super(props); this.state = {value: ' ...
状态提升 (共享状态)
09. 状态提升 (共享状态)通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。
在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”
两个输入框共享数据的例子:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127const scaleNames = { c: '摄氏度', f: '华氏度'};// 转摄氏度fu ...
组合vs继承
10.组合vs继承React 有十分强大的组合模式。我们推荐使用组合而非继承来实现组件间的代码重用。
包含关系 (组件组合)有些组件无法提前知晓它们子组件的具体内容。在 Sidebar(侧边栏)和 Dialog(对话框)等展现通用容器(box)的组件中特别容易遇到这种情况。
props的children属性(类似vue的插槽)我们建议这些组件使用一个特殊的 children prop 来将他们的子组件传递到渲染结果中:
12345678910111213141516171819202122function FancyBorder(props) { return ( <div className={'FancyBorder FancyBorder-' + props.color}> // children 是特殊的prop,在父组件中没有显式声明 {props.children} </div> );}function WelcomeDialog() ...
React哲学
11.React哲学(编写一个复杂组件的原则)React 最棒的部分之一是引导我们思考如何构建一个应用。在这篇文档中,我们将会通过 React 构建一个可搜索的产品数据表格来更深刻地领会 React 哲学。
从设计稿开始
第一步:将设计好的 UI 划分为组件层级首先,你需要在设计稿上用方框圈出每一个组件(包括它们的子组件)
你会看到我们的应用中包含五个组件。我们已经将每个组件展示的数据标注为了斜体。
FilterableProductTable (橙色): 是整个示例应用的整体
SearchBar (蓝色): 接受所有的用户输入
ProductTable (绿色): 展示数据内容并根据用户输入筛选结果
ProductCategoryRow (天蓝色): 为每一个产品类别展示标题
ProductRow (红色): 每一行展示一个产品
你可能注意到,ProductTable 的表头(包含 “Name” 和 “Price” 的那一部分)并未单独成为一个组件。这仅仅是一种偏好选择,如何处理这一问题也一直存在争论。(简单的可以不用单独分一个组件,复杂的作为一个独立的组件就有必要了)
组件层 ...