核心概念
JSX简介
JSX 防止注入攻击:react 会自动把用户输入的数据转换成 字符串。React DOM 在渲染所有输入内容之前,默认会进行转义
元素渲染
React 元素是构成 React 应用的最小砖块,是一个普通的对象,开销小,它代表了_某个特定时刻_ 的 UI。
React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。
React DOM 会 负责更新 DOM 来与 React 元素保持一致。
所以每次都是新创建一个 react 元素,然后传入 reactDOM.render(),然后 ReactDOM 负责比较上次和这次的元素状态,并且智只会更新一部分来达到效果
组件 & Props
注意: 组件名称必须以大写字母开头。
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,
<div />代表 HTML 的 div 标签,而<Welcome />则代表一个组件,并且需在作用域内使用Welcome。
事件处理
通常情况下,如果你没有在方法后面添加 (),例如 onClick={this.handleClick},你应该为这个方法绑定 **this**。
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({ isToggleOn: !state.isToggleOn }));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
如果没有使用 bind ,那就或者在调用的地方使用箭头函数
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
/**
* 此语法问题在于每次渲染 LoggingButton 时都会创建不同的回调函数。
* 在大多数情况下,这没什么问题,但如果该回调函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。
* 我们通常建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。
*/
列表 & Key
一般 key 用元素的 id,不到万不得已,不用 index
表单
在受控组件上指定 value 的 prop 会阻止用户更改输入。如果你指定了 value,但输入仍可编辑,则可能是你意外地将value 设置为 undefined 或 null。
下面的代码演示了这一点。(输入最初被锁定,但在短时间延迟后变为可编辑。)
ReactDOM.render(<input value="hi" />, mountNode);
setTimeout(function() {
ReactDOM.render(<input value={null} />, mountNode);
}, 1000);
高级指引
context
context 提供了一种在组件之间共享值的方式
类似插槽(位置在API目录上面一点点):react.docschina.org/docs/contex…
1、const MyContext = React.createContect(defaultValue):
提供一个MyContext对象,可以给任意组件订阅。订阅的组件从【组件树中离自己最近的Provider】获取值,如果没有匹配到会显示默认值,如果没有默认值 消费组件的默认值不会生效**2、MyContext.provider()
**_
- 当 Provider 的
value值发生变化时,它内部的所有消费组件都会重新渲染。从 Provider 到其内部 consumer 组件(包括 .contextType 和 useContext)的传播不受制于shouldComponentUpdate函数,因此当 consumer 组件在其祖先组件跳过更新的情况下也能更新。(自我理解:不触发父组件的更新,但是可以更新自身的 context 数据)- <MyContext.Provider value={/* 某个值 */}>
- 注意避免 本组就更新的时候影响子组件更新。 context会根据引用标识的value值的变化来决定渲染(本质是浅比较)
_
3、MyContext.consumer (函数式接收)
注意这种方法需要在中间使用一个函数来接收,其中 value 是 context
**
<MyContext.Consumer> {value => /* 基于 context 值进行渲染*/} </MyContext.Consumer>5、class.contextType(类接收)
**
挂载在 class 上的
contextType属性可以接收 最近 Context 上的值。你可以在任何生命周期中用 this.context 访问到它,包括 render 函数中。你只通过该 API 订阅单一 context。如果你想订阅多个,阅读使用多个 Context 章节
class MyClass extends React.Component { static contextType = MyContext; render() { let value = this.context; /* 基于这个值进行渲染工作 */ } }
4、MyContext.displayName()