React 如何实现它的双向数据绑定?
Posted
技术标签:
【中文标题】React 如何实现它的双向数据绑定?【英文标题】:How does React implement its two-way data binding? 【发布时间】:2019-03-24 21:29:15 【问题描述】:我已经看到 examples 展示了如何在 React 中实现双向绑定,但没有人解释此功能实际上是如何在内部发挥作用的。
在这个来自 React 网站的 codepen example 中,如果你注释掉第 11 行:
handleChange(event)
// this.setState(value: event.target.value);
您会注意到 React 如何通过确保视图不会以与数据模型不一致的方式更新来强制执行 2-way 绑定,即使在用户直接修改输入框之后也是如此。但它是如何做到的呢?
考虑到event.target.value
有用户刚刚在handleChange
范围内输入的输入,但在视图中仍然为空,这意味着在某些时候该值被 React 重置。另外,它不是简单地将值重置为空,而是根据最新的数据模型,可以通过对代码进行以下更改来测试:
constructor(props)
super(props);
this.state = value: '';
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.counter = 0;
handleChange(event)
if (this.counter < 3)
this.setState(value: event.target.value);
this.counter++;
这一次,输入框改变了前三次,然后根据最后一个模型状态重置。
我的猜测如下:
-
html 元素根据用户输入进行修改。
“onchange”事件处理程序被触发。
状态未更新。
由于状态未更新,React 将组件的缓存 Virtual-DOM 表示与用户刚刚更改的 Real-DOM 元素进行比较。
React 更新 Real-DOM 元素的属性,使其与其 Virtual-DOM 表示一致。
如果状态发生了变化,那么缓存的 Virtual-DOM 表示会被“弄脏”,这会触发虚拟元素的重新渲染。但是,我上面描述的其余流程仍然适用,这意味着不会创建新的 HTML 节点,只会更新现有节点的属性(假设元素类型,例如 <input>
,没有t改变)。
这是我对该功能的内部机制可能的最佳猜测。如果我错了,请告诉我,如果是,问题的真正答案是什么。
谢谢!
【问题讨论】:
【参考方案1】:这是一个巧妙的问题,我会尽力而为,如果有人在我的回答中发现任何错误,请指出,我很乐意编辑更正!挖掘 React 源代码是我想出的:
1 - 修改 HTML 并在 DOM 中调用事件
2 - React 将EventPropoagators.js 内的事件/合成事件调度排队
3 - 事件按顺序出队(此事件对状态没有影响)
4 - 在事件循环结束时,react 使用restoreTarget
来恢复受控组件以表示React Controlled Component.js 中的状态:
用于在更改事件触发后恢复受控状态。
我们在事件循环结束时执行此转换,以便我们 始终在此处接收正确的光纤
这就是魔法发生的地方。 restoreTarget
是一个组件的 state
,因此此时 react 会触发一个常规的 render()
以重绘 restoreTarget
,我想这将通过它的标准虚拟 DOM 与真实 DOM 协调算法。
根据您的示例,handleChange()
被执行(有或没有状态更改),然后重绘restoreTarget
并呈现一个组件,该组件准确表示count = 3
所在时刻的状态。
【讨论】:
很遗憾,您的链接已损坏,仅提供 404。【参考方案2】:我将通过一个示例展示 React 的双向绑定是如何工作的。 设置一个 React 应用程序
App.js
import React, Component from 'react';
import './App.css';
import Person from './Person/Person';
class App extends Component
state =
persons: [
name: "VK",
age: 29
,
name: "HK",
age: 28
]
nameChangedHandler = (event) =>
this.setState(
persons: [
name: "VK",
age: 29
,
name: event.target.value,
age: 28
],
groupName: "Vishita"
);
render()
return (
<div className="App">
<h1>Vinit Khandelwal</h1>
<p>And here is my resume</p>
<Person
name=this.state.persons[0].name
age=this.state.persons[0].age />
<Person
name=this.state.persons[1].name
age=this.state.persons[1].age
changed=this.nameChangedHandler >Hobby: Shopping</Person>
</div>
);
export default App;
Person > Person.js
import React from 'react';
const person = (props) =>
return (
<div>
<p>I am props.name. I am props.age years old!</p>
<p onClick=props.click>props.children</p>
<input type="text" onChange=props.changed value=props.name />
</div>
);
export default person;
这个例子展示了 React 中的两种绑定方式:定义函数和调用函数,传递事件和使用事件的值。
【讨论】:
以上是关于React 如何实现它的双向数据绑定?的主要内容,如果未能解决你的问题,请参考以下文章