我经历了詹姆斯·尼尔森的Learn React.js (without JSX)系列。本系列介绍了使用React实现的表单,并显示输入字段是有效只读的,然后继续解释如何正确更改值。这是不关于如何这样做的问题。相反,我想了解React如何防止值发生变化。
以下代码(也在jsfiddle中)是SSCCE:
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js"></script>
</head>
<body>
<div>
<h3>simple HTML form (no ReactJS)</h3>
<form>
<input type='text' value placeholder='please enter your name'>
</form>
</div>
<div id='react-app'>
<script type='text/javascript'>
const rce = React.createElement.bind(React);
const rcc = React.createClass.bind(React);
const ContactForm = rcc({
propTypes: {
value: React.PropTypes.object.isRequired,
},
render: function() {
return rce('form', {}
, rce('input', {type: 'text'
, placeholder: 'please enter your name'
, value: this.props.value.name
, onInput: function(se) {
console.log(se.target.value);
}}))}
, componentWillMount : function () {console.log('componentWillMount');}
, componentDidMount : function () {console.log('componentDidMount');}
, componentWillReceiveProps: function () {console.log('componentWillReceiveProps');}
, shouldComponentUpdate : function () {console.log('shouldComponentUpdate');}
, componentWillUpdate : function () {console.log('componentWillUpdate');}
, componentDidUpdate : function () {console.log('componentDidUpdate');}
, componentWillUnmount : function () {console.log('componentWillUnmount');}
});
const ContactView = rcc({
propTypes: {
newContact: React.PropTypes.object.isRequired,
}
,render: function () {
console.log('render called');
return rce('div', {}
, rce('h3', {}, 'why doesn\'t the input field value change?')
, rce(ContactForm, {
value: this.props.newContact
}))
}
});
var reactApp = rce(ContactView, {newContact: {name: ''}});
ReactDOM.render(reactApp, document.getElementById('react-app'));
</script>
</body>
</html>
上面的代码生成两个html表单:一个用简单的HTML创建,另一个用ReactJS创建。呈现的元素是相同的:
对于简单的HTML表单:
对于使用ReactJS创建的HTML表单:
我正在控制台上为每个被调用的组件生命周期方法记录消息。唯一似乎被调用的是render
,componentWillMount
和componentDidMount
(仅在开头)。在输入文本字段中输入击键时,不会调用后续生命周期方法。
所以我的问题是:假设没有调用其他生命周期方法,ReactJS如何管理以防止输入字段值发生变化,因为其DOM表示 相同 一个简单的HTML表单输入字段(当我在输入字段中键入时,我的浏览器中显示的值确实确实改变了)?
答案 0 :(得分:4)
React使用virtual DOM的概念。它的作用是“虚拟地”跟踪变化,并用这种抽象取代“真正的”DOM。
当(重新)渲染组件时,它将虚拟DOM映射到“真实”DOM。将输入字段值限制为通过props
收到的值后,它不会更改(因为您不会更改props
)。
如果您希望将值与您输入的内容保持同步,则可以将值绑定到组件state
。
关于你的第二个问题,我没有完全关注,但你可能想看看component's lifecycle。这使您可以在发生某些更改时控制组件(例如,传递新的道具)。
由于我认为我不清楚,请让我详细说明一下。
根据docs:
<input type="text" name="title" value="Untitled" />
这将使用值Untitled
呈现输入已初始化。当用户更新输入时,节点的value
属性将更改。但是,node.getAttribute('value')
仍将返回初始化时使用的值Untitled
。
[属性与价值可能让我感到困惑。 Here's an explanatory post.]
与HTML不同,React组件必须在任何时间点表示视图的状态,而不仅仅是在初始化时。例如,在React中:
render: function() {
return <input type="text" name="title" value="Untitled" />;
}
由于此方法在任何时间点描述视图,因此文本输入的值始终为Untitled
。