React文档漫步-核心概念
JSX
const element1 = <h1>Hello, world!</h1>;
const name = 'Josh Perez';
const element2 = <h1>Hello, {name}</h1>;
-
在 JSX 语法中,你可以在大括号内放置任何有效的 JavaScript 表达式。
-
JSX本身也是一个表达式
-
指定属性采用大驼峰
-
Babel 会把 JSX 转译成一个名为
React.createElement()
函数调用,返回一个对象。 -
返回的对象我们称为React元素
const element = ( <h1 className="greeting"> Hello, world! </h1> ); // 等效 const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' ); // 实际上它创建了一个这样的对象。注意:这是简化过的结构 const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world!' } };
元素渲染
- React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。
- 尽管每一秒都会新建一个描述整个 UI 树的元素,React DOM 只会更新实际改变了的内容
组件&props
组件类似js函数:接收任意的props,返回React元素。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
- 组件名称必须以大写字母开头
- 建议从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。
- 所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
State&生命周期
- 不要直接修改State
- State是异步的
- State更新会被浅合并
- 数据是向下流动的。
- 如果你把一个以组件构成的树想象成一个 props 的数据瀑布的话,那么每一个组件的 state 就像是在任意一点上给瀑布增加额外的水源,但是它只能向下流动。
事件处理
-
事件命名采用小驼峰式
-
JSX里事件需要传入一个函数
-
// HTML <button onclick="activateLasers()"> Activate Lasers </button>
-
// jsx <button onClick={activateLasers}> Activate Lasers </button>
-
-
阻止表单的默认提交行为
-
// HTML <form onsubmit="console.log('You clicked submit.'); return false"> <button type="submit">Submit</button> </form>
-
function Form() { function handleSubmit(e) { e.preventDefault(); console.log('You clicked submit.'); } return ( <form onSubmit={handleSubmit}> <button type="submit">Submit</button> </form> ); }
-
-
class语法记得绑定this
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
列表&Key
- key 帮助 React 识别哪些元素改变了,因此应当给数组中的每一个元素赋予一个确定的标识。
- 一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串
- 不建议使用索引来用作 key 值
- key 在其兄弟节点之间应该是独一无二的,不需要全局唯一
组合&继承
1. 包含关系
// 使用children传递组件
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-' + props.color}>
{props.children}
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
// 使用参数传递组件
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts />
}
right={
<Chat />
} />
);
}
2.特例关系
// WelcomeDialog 可以说是 Dialog 的特殊实例。
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome"
message="Thank you for visiting our spacecraft!" />
);
}
React哲学
- 前提:设计稿,接口
- 第一步:UI划分组件层级。
- 一个组件原则上只能负责一个功能。
- 如果你的模型设计得恰当,UI(或者说组件结构)便会与数据模型一一对应
- 第二步:写React静态页面
- 编写一个应用的静态版本时,往往要编写大量代码,而不需要考虑太多交互细节;添加交互功能时则要考虑大量细节,而不需要编写太多代码。所以,将这两个过程分开进行更为合适。
- 需要创建一些会重用其他组件的组件,然后通过 props 传入所需的数据
- 完全不应该使用 state 构建静态版本
- 对于较为大型的项目来说,自下而上地构建,并同时为低层组件编写测试是更加简单的方式。
- 第三步:确定UI state 的最小完整表示
- state 用来触发数据模型改变,使UI具备交互功能
- 需要找出应用所需的 state 的最小表示,并根据需要计算出其他所有数据。
- 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
- 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
- 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。
- 第四步:确定 state 的位置
- 找到根据这个 state 进行渲染的所有组件。
- 找到他们的共同所有者(common owner)组件(在组件层级上高于所有需要该 state 的组件)。
- 该共同所有者组件或者比它层级更高的组件应该拥有该 state。
- 如果你找不到一个合适的位置来存放该 state,就可以直接创建一个新的组件来存放该 state,并将这一新组件置于高于共同所有者组件层级的位置。
- 第五步:添加反向数据流。显式声明监听函数,并用callback调用setState(),来更新应用。
本文来自博客园,作者:沧浪浊兮,转载请注明原文链接:https://www.cnblogs.com/shixiu/p/16514532.html