为了便于阅读,建议将jsx拆分为多行,并且将内容用()包裹,这可以避免遇到自动插入分号陷阱。
注:自动插入分号ASI(auto semicon insertion)
在以 ([/+- 开头的语句前加分号
React DOM 使用 camelCase
(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。class 变为className , tabindex 变为tabIndex。
JSX可以防止 XSS(cross-site-scripting, 跨站脚本)攻击。
Babel 会把 JSX 转译成一个名为 React.createElement()
函数调用。
以下两种代码完全等效:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
想要将一个元素渲染到跟DOM节点中,只需把它们一起传入 ReactDOM.render()
React 元素是不可变对象。
考虑 UI 在任意给定时刻的状态,而不是随时间变化的过程,能够消灭一整类的 bug。
React 元素也可以是用户自定义的组件
注意: 组件名称必须以大写字母开头。
从组件自身的角度命名 props,而不是依赖于调用组件的上下文命名。
所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
纯函数:不会尝试更改入参,且多次调用下相同的入参始终返回相同的结果。
function sum(a, b) {
return a + b;
}
react class方式声明:
当State中的某个状态发生变化,我们应该重新创建这个状态对象,而不是直接修改原来的状态。
正确渲染state:
调用setState()方法来更新state的状态,且构造函数是唯一可以给this.state赋值的地方
出于性能考虑,React 可能会把多个 setState()
调用合并成一个调用。
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
当你调用 setState()
的时候,React 会把你提供的对象合并到当前的 state。组件State的更新是一个浅合并的过程。
任何的 state 总是所属于特定的组件,而且从该 state 派生的任何数据或 UI 只能影响树中“低于”它们的组件。
如果需要组织事件的默认行为,必须显式的调用 preventDefault
引出
绑定事件处理函数作用域的方式
利用bind方法
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
你可以在回调中使用箭头函数,不推荐,每次会创建一个新的函数,当做参数传入子组件,可能会进行额外的重新渲染
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
render() {
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
class fields 语法
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
// 注意: 这是 *实验性* 语法。
handleClick = () => {
console.log('this is:', this);
}
向事件处理程序传递参数
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
使用箭头函数绑定事件时,需要显示传递事件对象e
与运算符 &&
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
在 JavaScript 中,true && expression
总是会返回 expression
, 而 false && expression
总是会返回 false
。
在极少数情况下,你可能希望能隐藏组件,即使它已经被其他组件渲染。若要完成此操作,你可以让 render
方法直接返回 null
,而不进行任何渲染。
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
Warning!
</div>
);
}
在组件的 render
方法中返回 null
并不会影响组件的生命周期。
key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。
给数组元素赋予确定标识的方式
使用元素的id
使用索引index。如果你选择不指定显式的 key 值,那么 React 将默认使用索引用作为列表项目的 key 值。如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。example
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);
元素的 key 只有放在就近的数组上下文中才有意义。即放在数组元素上,不论数组元素是原生标签还是自定义组件。
这个 key 不需要全局唯一,但在列表中需要保持唯一。
key 会传递信息给 React ,但不会传递给你的组件。如果你的组件中需要使用 key
属性的值,请用其他属性名显式传递这个值:
const content = posts.map((post) =>
<Post
key={post.id}
id={post.id}
title={post.title} />
);
如果一个 map()
嵌套了太多层级,那可能就是你提取组件的一个好时机。
引出
React 在以下两个假设的基础之上提出了一套 O(n) 的启发式算法:
- 两个不同类型的元素会产生出不同的树;
- 开发者可以通过
key
prop 来暗示哪些子元素在不同的渲染下能保持稳定;react tree diff 在处理层级移动时,会重新创建整个层级,影响性能。可以使用CSS显示或隐藏节点,而不是真的添加和删除节点。
在开发过程中,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。
当需要处理多个 input
元素时,我们可以给每个元素添加 name
属性,并让处理函数根据 event.target.name
的值选择要执行的操作。
在受控组件上指定 value 的 prop 可以防止用户更改输入。如果指定了 value
,但输入仍可编辑,则可能是意外地将value
设置为 undefined
或 null
受控组件
非受控组件
在 React 中,<input type="file" />
始终是一个非受控组件,因为它的值只能由用户设置,而不能通过代码控制。
引出
使用受控组件的条件
- 就地反馈,如表单即时验证
- 除非所有的字段都有效,否则禁用提交按钮
- 强制执行特定的输入格式,如信用卡号码
ref
属性用于 HTML 元素时,构造函数中使用 React.createRef()
创建的 ref
接收底层 DOM 元素作为其 current
属性。ref
属性用于自定义 class 组件时,ref
对象接收组件的挂载实例作为其 current
属性。Ref 转发使组件可以像暴露自己的 ref 一样暴露子组件的 ref
回调方式
通过React.createRef()方式创建
render
中的元素时,对该节点的引用可以在 ref 的 current
属性中被访问。你应当依靠自上而下的数据流,而不是尝试在不同组件间同步 state。
虽然提升 state 方式比双向绑定方式需要编写更多的“样板”代码,但带来的好处是,排查和隔离 bug 所需的工作量将会变少。
如果某些数据可以由 props 或 state 推导得出,那么它就不应该存在于 state 中。
特殊prop属性children ,类似于Vue中的插槽
实现具名插槽
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 />
} />
);
}
常用于组件复用UI功能
对于非UI功能的复用,组件可以直接引入(import)而无需通过 extend 继承它们。
原文:https://www.cnblogs.com/goOtter/p/10955399.html