Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。react
1
2
3
4
5
6
7
8
9
|
render () {
return (
<ul>
{this.state.todoItems.map(({item, key}) => {
return <li key={key}>{item}</li>
})}
</ul>
)
}
|
在开发过程当中,咱们须要保证某个元素的 key 在其同级元素中具备惟一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近建立的仍是被移动而来的元素,从而减小没必要要的元素重渲染。此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系,所以咱们毫不可忽视转换函数中 Key 的重要性。git
在代码中调用 setState 函数以后,React 会将传入的参数对象与组件当前的状态合并,而后触发所谓的调和过程(Reconciliation)。通过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树而且着手从新渲染整个 UI 界面。在 React 获得元素树以后,React 会自动计算出新的树与老树的节点差别,而后根据差别对界面进行最小化重渲染。在差别计算算法中,React 可以相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是所有从新渲染。github
shouldComponentUpdate 这个方法用来判断是否须要调用 render 方法从新描绘 dom。由于 dom 的描绘很是消耗性能,若是咱们能在 shouldComponentUpdate 方法中可以写出更优化的 dom diff 算法,能够极大的提升性能。web
虚拟 dom 至关于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操做,从而提升性能。ajax
用 JavaScript 对象结构表示 DOM 树的结构;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变动的时候,从新构造一棵新的对象树。而后用新的树和旧的树进行比较,记录两棵树差别把 2 所记录的差别应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。算法
Refs 是 React 提供给咱们的安全访问 DOM 元素或者某个组件实例的句柄。咱们能够为元素添加 ref 属性而后在回调函数中接受该元素在 DOM 树中的句柄,该值会做为回调函数的第一个参数返回:redux
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class CustomForm extends Component {
handleSubmit = () => {
console.log("Input Value: ", this.input.value)
}
render () {
return (
<form onSubmit={this.handleSubmit}>
<input
type='text'
ref={(input) => this.input = input} />
<button type='submit'>Submit</button>
</form>
)
}
}
|
上述代码中的 input 域包含了一个 ref 属性,该属性声明的回调函数会接收 input 对应的 DOM 元素,咱们将其绑定到 this 指针以便在其余的类函数中使用。另外值得一提的是,refs 并非类组件的专属,函数式组件一样可以利用闭包暂存其值:promise
1
2
3
4
5
6
7
8
9
10
11
|
function CustomForm ({handleSubmit}) {
let inputElement
return (
<form onSubmit={() => handleSubmit(inputElement.value)}>
<input
type='text'
ref={(input) => inputElement = input} />
<button type='submit'>Submit</button>
</form>
)
}
|
1
2
3
4
5
|
<Twitter username='tylermcginnis33'>
{(user) => user === null
? <Loading />
: <Badge info={user} />}
</Twitter>
|
1
2
3
4
5
6
7
|
import React, { Component, PropTypes } from 'react'
import fetchUser from 'twitter'
// fetchUser take in a username returns a promise
// which will resolve with that username's data.
class Twitter extends Component {
// finish this
}
|
若是你还不熟悉回调渲染模式(Render Callback Pattern),这个代码可能看起来有点怪。这种模式中,组件会接收某个函数做为其子组件,而后在渲染函数中以 props.children 进行调用:浏览器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import React, { Component, PropTypes } from 'react'
import fetchUser from 'twitter'
class Twitter extends Component {
state = {
user: null,
}
static propTypes = {
username: PropTypes.string.isRequired,
}
componentDidMount () {
fetchUser(this.props.username)
.then((user) => this.setState({user}))
}
render () {
return this.props.children(this.state.user)
}
}
|
这种模式的优点在于将父组件与子组件解耦和,父组件能够直接访问子组件的内部状态而不须要再经过 Props 传递,这样父组件可以更为方便地控制子组件展现的 UI 界面。譬如产品经理让咱们将本来展现的 Badge 替换为 Profile,咱们能够轻易地修改下回调函数便可:缓存
1
2
3
4
5
|
<Twitter username='tylermcginnis33'>
{(user) => user === null
? <Loading />
: <Profile info={user} />}
</Twitter>
|
在HTML 中,相似 <input>
, <textarea>
和 <select>
这样的表单元素会维护自身的状态,并基于用户的输入来更新。当用户提交表单时,前面提到的元素的值将随表单一块儿被发送。但在 React 中会有些不一样,包含表单元素的组件将会在 state 中追踪输入的值,而且每次调用回调函数时,如 onChange 会更新 state,从新渲染组件。一个输入表单元素,它的值经过 React 的这种方式来控制,这样的元素就被称为”受控元素”。
高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最多见的多是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。若是你发现你在不一样的地方写了大量代码来作同一件事时,就应该考虑将代码重构为可重用的 HOC。
由于 this.props 和 this.state 的更新多是异步的,不能依赖它们的值去计算下一个 state。
你可使用属性初始值设定项(property initializers)来正确绑定回调,create-react-app 也是默认支持的。在回调中你可使用箭头函数,但问题是每次组件渲染时都会建立一个新的回调。
在 super() 被调用以前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的缘由则是便于(在子类中)能在 constructor 访问 this.props。
在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是,你不能保证在组件挂载以前 Ajax 请求已经完成,若是是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起做用。在 componentDidMount 中发起网络请求将保证这有一个组件能够更新了。
为了解决跨浏览器兼容性问题,您的 React 中的事件处理程序将传递 SyntheticEvent 的实例,它是 React 的浏览器本机事件的跨浏览器包装器。
这些 SyntheticEvent 与您习惯的原生事件具备相同的接口,除了它们在全部浏览器中都兼容。有趣的是,React 实际上并无将事件附加到子节点自己。React 将使用单个事件监听器监听顶层的全部事件。这对于性能是有好处的,这也意味着在更新 DOM 时,React 不须要担忧跟踪事件监听器。
React.createElement():JSX 语法就是用 React.createElement()来构建 React 元素的。它接受三个参数,第一个参数能够是一个标签名。如 div、span,或者 React 组件。第二个参数为传入的属性。第三个以及以后的参数,皆做为组件的子组件。
1
2
3
4
5
|
React.createElement(
type,
[props],
[...children]
)
|
React.cloneElement()与 React.createElement()类似,不一样的是它传入的第一个参数是一个 React 元素,而不是标签名或组件。新添加的属性会并入原有的属性,传入到返回的新元素中,而就的子元素奖杯替换。
1
2
3
4
5
|
React.cloneElement(
element,
[props],
[...children]
)
|
React.createClass()、ES6 class 和无状态函数。
Flux 的最大特色,就是数据的”单向流动”。
creat-react-app Yeoman 等