First of all, we need to understand what the role of learning V-model is.
By default, a V-Model on a component makes use of a prop named Value and an event named input, but input controls of types like checkboxes, checkboxes, and so on May use value attributes for different purposes. The Model option can be used to avoid such conflicts — this is the solution found on the VUE website.
Second, we need to know the nature of the V-Model and how it works.
In my opinion, V-Model itself is a syntactic sugar. In fact, it provides us with a built-in vUE instruction. In this way, it not only simplifies our code but also enables us to understand how to use this command
Using the V-Model command allows us to retrieve the input directly from the input box, save the input to our data, and update the data automatically when the input value changes as well as update the corresponding view rendering.
<div class="about"> <p>{{model}}</p> <! -- v-model --> <input type="text" v-model="model"> </div> </template> <script> export default { data() { return { model:'', } }, } </script>Copy the code
The idea behind bidirectional binding MVVM is to listen for data and update the page view as it changes.
The flow chart of MVVM
Here is how bidirectional binding works, using data hijacking and template parsing to listen to our view of data updates through a step-by-step process
Observer data hijacks related code
An Observer is actually an Observer that listens to every item in our data through a loop. When the data changes, it will send updates to subscribers through notify method, and Compile our text at the same time to realize partial view updates.
Class Observe {constructor(vm) {this.walk(vm)} class Observe {constructor(vm) {this.walk(vm) { Object.keys(data).forEach( key => { this.defineReactive(data, key, DefineReactive (data, key, defineReactive) Value) {let dep = new dep () object.defineProperty (data, key, {get() {console.log(' trigger get collection dependency '); If (dep.target) {// Add subscriber dep.addSub(dep.target)} return value}, set(newValue) {console.log(value, 'trigger set to distribute updates '); Value = newValue // Send update dep.notify()},})}}Copy the code
Watcher view updated
Watcher is our subscriber and updates the view through the update method
constructor(vm, exp, cb ) { this.vm = vm; this.exp = exp; this.cb = cb; This.value = this.get()} update() {this.run()} // update DOM run() {const value = this.get() ! == this.value) {// Call the callback this.cb.call(this.vm, Get () {dep.target = this let value = this.vm.data[this.exp] dep.target = null; return value } }Copy the code
This is my understanding of bidirectional binding. It is not comprehensive enough. I hope you can criticize and correct me.