Some comments said UI5 use Handlebars for data binding, and after search, Handlebars only support for one-time data binding. What I am more curious is how two-way data binding implemented in UI5(Sorry for not making this clear in the first place).
In Handlebars,once you compiled your template, the view/DOM has nothing to do with the data model.
But two-way data binding connects data to a property or attribute of an element in its local DOM. Which means:
When properties in the model get updated, so does the UI. When UI elements get updated, the changes get propagated back to the model.
  https://stackoverflow.com/a/13504965/5238583 
In the question of How to Implement DOM Data Binding in JavaScript
, many techniques are mentioned. UI5 uses these two(what I've found so far): add change event listener and mutators(setter)
I used this official sample for example: Data Binding - Step 13 - Element Binding
data binding changes when
oProductDetailPanel.bindElement({ path: sPath, model: "products" }); is called.
Set break points in oBinding.setContext() in ManagedObject.prototype.updateBindingContext and ManagedObject.prototype.updateProperty. And you can see it in call stack. 
TL;DR: Core steps are 3, 6, 8
The main steps are: 
- Element.prototype.bindElementequals to ManagedObject.prototype.bindObject
 
- oBinding.initialize() which means ClientContextBinding.prototype.initialize is called in - ManagedObject.prototype._bindObject
 
- Binding.prototype._fireChange is called in the - createBindingContextcallback. Which fire- changeevent:- this.fireEvent("change", mArguments);
 
- And! The change event handler is defined in - ManagedObject.prototype._bindObject:
 - var fChangeHandler = function(oEvent) {
     that.setElementBindingContext(oBinding.getBoundContext(), sModelName);
};
oBinding.attachChange(fChangeHandler);
oBindingInfo.modelChangeHandler = fChangeHandler;
 
- setElementBindingContext()calls- ManagedObject.prototype.updateBindingContexteventually
 
- In - updateBindingContext, the call stack is- oBinding.setContext(oContext)->- JSONPropertyBinding.prototype.checkUpdate(because the sample use JSON Model here) ->- this._fireChange({reason: ChangeReason.Change})
 
- For the second change event, the handler is in ManagedObject.prototype._bindProperty (There are many - fModelChangeHandlerin bind functions of ManagedObject, For our- bindElementsample, we only need this one)
 
- In the - fModelChangeHandler,- ManagedObject.prototype.updatePropertyis called. That where our setter(mutator) is used:
 
whenever a property binding is changed.This method gets the external format from the property binding and applies it to the setter.
this[oPropertyInfo._sMutator](oValue);. For our sample oPropertyInfo._sMutator is setValue. execute this, the value in Input <Input value="{products>ProductID}"/> will be changed. 
Original record here: https://github.com/TinaC/Blog/blob/master/SAPUI5/Data_Binding.md