As a JavaScript developer who has a lot of experience with jQuery but new to frameworks like Knockout or Angular, when React emphasizes it is a one-way data binding vs two-way data binding of the other two frameworks, I was kind of confused.
React: "React implements one-way reactive data flow which reduces boilerplate and is easier to reason about than traditional data binding"
After a few more reading, actually it is dead simple. One-way data binding is just about not doing something than about doing something.
Let's use jQuery as example to explain what it is. Let's start with a zero-way data binding or no data binding at all.
Zero-way data binding
It is just HTML with no script.
<input class="myInput" type="text" />
no script, no data binding. Isn't that simple?
One-way data binding
<input class="myInput" type="text" />
<script>
var data = 'hello world';
$('.myInput').val(data)
</script>
When the script runs, it one-way initializes the HTML control to a value.
Two-way data binding
<input class="myInput" type="text" /> <script> var data = 'hello world'; $('.myInput').val(data); $('.myInput').onchange(function(){ data = $(this).val(); //update any other 1000 controls who uses data too }) </script>As you can see, after the one-way initializing the input control, the "onchange" event handler updates the data and other 1000 controls who use the data. This the 2nd direction of data flow: from UI to data.
React's Data Binding
The confusion I had is that why they are all saying React is one-way data binding, when definitely you can use same event handler to implement two-way data binding. It turns out that it is called so just because you have to implement two-way binding by code explicitly instead of implicitly as in the other frameworks.
So this React's one-way data binding
var SearchBox = React.createClass({ getInitialState: function(){ return {currInput: 'hello world'} }, render: function(){ var currInput = this.state.currInput; return ( <div> <input type="text" value={currInput} /> <div>{currInput}</div> </div> ); } }); React.render(<SearchBox />, $('.myContent')[0])
The HTML controls are initialized with the state/data at one direction. The reason it is not two-way yet is just that we haven't implement anything that will flow data from UI to state/data.
React's "two-way data binding"
var SearchBox = React.createClass({
getInitialState: function(){
return {currInput: 'hello'}
},
handleKey: function(e)
{
this.setState({currInput: this.state.currInput + e.key });
},
render: function(){
var currInput = this.state.currInput;
return (
<div>
<input type="text" value={currInput} onKeyPress={this.handleKey} />
<div>{currInput}</div>
</div>
);
}
});
React.render(<SearchBox />, $('.myContent')[0])
Call this code "two-way" is kind of misleading. When you have to do something explicitly by code, it is not "two-way". It is still one way because "two-way" means two direction data flow automatically implicitly by framework. When you have do it by code, it is "your way" not "two-way". Stop playing the word game! :-)Why it is good?
It is good just because it falls in the pattern that "less unknown is good when complexity grows". When the framework doing a lot for you automatically, implicitly in a big application, you will get lost. For a simpler application, it is just great since you write fewer code.
For example:
return (
<div>
<input type="text" value={currInput} onKeyPress={this.handleKey} />
<div>{currInput}</div>
<div>{currInput}</div>
<div>{currInput}</div>
<div>{currInput}</div>
<div>{currInput}</div>
// a 1000 div use currInput <div>{currInput}</div>
</div>
);
Here the beauty is that we have to write a 1000 lines of <div> to clearly say that another 1000 controls will be affected.Why the other framework's two-way binding is bad?
<head>
<title>Observable 2</title>
<script src="Scripts/jquery-1.11.0.min.js"></script>
<script src="Scripts/knockout-3.2.0.js"></script>
<script>
function myViewModel1() {
this.myData1 = ko.observable('hello world');
}
$(function () {
ko.applyBindings(new myViewModel1());
});
</script>
</head>
<body>
<input data-bind="value: myData1, valueUpdate: 'keyup'" />
<input data-bind="value: myData1, valueUpdate: 'keyup'" />
<input data-bind="value: myData1, valueUpdate: 'keyup'" />
<input data-bind="value: myData1, valueUpdate: 'keyup'" />
// could have 1000 input anywhere in the page
<input data-bind="value: myData1, valueUpdate: 'keyup'" />
<div class="myDiv" data-bind="text: myData1"></div>
<div class="myDiv" data-bind="text: myData1"></div>
<div class="myDiv" data-bind="text: myData1"></div>
<div class="myDiv" data-bind="text: myData1"></div>
<div class="myDiv" data-bind="text: myData1"></div>
// could have 1000 div anywhere in the page
<div class="myDiv" data-bind="text: myData1"></div>
</body>
As you can see the two-way data binding of Knockout make things are so simple, only a few lines of JavaScript codes are needed to bind a few thousands of controls all together to a single data.
Any input can take a change and the change is made automatically to the other few thousands controls.
This is bad because in a large app, it really hard to keep track where are all these thousands of controls and data flow is a mess.
The power of two-way binding.
With this sample, you can feel the power/mess of two-way data bind of knockout. Typing in any of the input box will change anything else on the page. Imagine this a large single page application with controls everywhere.
http://facebook.github.io/react/docs/two-way-binding-helpers.html
http://n12v.com/2-way-data-binding/
No comments:
Post a Comment