SoFunction
Updated on 2025-04-05

Understand the principles of two-way data binding in Vue

Changes in data are reflected to the view

We learned earlier that after data hijacking, we can do whatever we want after the data is modified, and the operation view is of course OK.

Imperative operation view

Goal: We can use the original operation of the dom to enable the latest value of each name to be displayed inside the p element.

<div >
  <p></p>
</div>
<script>
   let data = {
        name: 'Xiaolan',
        age: 18,
        height:180
    }
    // traverse each property    (data).forEach((key)=>{
        // key attribute name        // data[key] attribute value        defineReactive(data,key,data[key])
    })
    function defineReactive(data,key,value){
        (data,key,{
            get(){
               return value
            },
            set(newVal){
              value = newVal 
              // The data changes, the operation dom is updated              ('#app p').innerHTML = 
            }
        })
    }
  // First rendering  ('#app p').innerHTML = 
</script>

Declarative operation view

Goal: We render the value of the name attribute in data as text to the p tag marked with v-text. In vue, we call this tokenized declarative rendering instruction

<div >
  <p v-text="name"></p>
</div>
<script>
  let data = {
    name: 'Xiaolan',
    age: 18,
    height: 180
  }
  // traverse each property  (data).forEach((key) => {
    // key attribute name    // data[key] attribute value    // data original object    defineReactive(data, key, data[key])
  })
  function defineReactive(data, key, value) {
    (data, key, {
      get() {
        return value
      },
      set(newVal) {
        value = newVal
        // The data changes, the operation dom is updated        compile()
      }
    })
  }
  // 
  function compile() {
    let app = ('app')
    // 1. Get all the sub-elements in the app    const nodes =    //  [text, input, text]
    //2. Iterate through all child elements    (node => {
      // nodeType is 1 for element node      if ( === 1) {
        const attrs = 
        // traverse all attrubites to find v-model        (attrs).forEach(attr => {
          const dirName = 
          const dataProp = 
          if (dirName === 'v-text') {
             = data[dataProp]
          }
        })
      }
    })
  }
  // First rendering  compile()
</script>

summary

Whether it is a instruction or an interpolation expression, these are just marks that reflect data to the view. Through marking, we can react the data's change response to the corresponding dom position.
The process of finding tags and binding data to the dom is called binding

Changes in the view reflect to the data

Objective: Render the corresponding value of the message attribute in data onto input. At the same time, after the input value is modified, the message value can be modified in reverse. In the vue system, the v-model instruction does this. Let's implement the function of v-model

<div >
  <input v-model="name" />
</div>
<script>
  let data = {
    name: 'Xiaolan',
    age: 18,
    height: 170
  }
  // traverse each property  (data).forEach((key) => {
    // key attribute name    // data[key] attribute value    // data original object    defineReactive(data, key, data[key])
  })
  function defineReactive(data, key, value) {
    (data, key, {
      get() {
        return value
      },
      set(newVal) {
        // The data changes, the operation dom is updated        if (newVal === value) {
          return
        }
        value = newVal
        compile()
      }
    })
  }
  // Compile the function  function compile() {
    let app = ('app')
    // 1. Get all the sub-elements in the app    const nodes =    //  [text, input, text]
    //2. Iterate through all child elements    (node => {
      // nodeType is 1 for element node      if ( === 1) {
        const attrs = 
        // traverse all attrubites to find v-model        (attrs).forEach(attr => {
          const dirName = 
          const dataProp = 
          if (dirName === 'v-model') {
             = data[dataProp]
            // View changes are reflected to data, nothing more than event listening reverse modification            ('input', (e) => {
              data[dataProp] = 
            })
          }
        })
      }
    })
  }
  // First rendering  compile()
</script>

Existing problems

Unable to achieve accurate updates

<div >
  <p v-text="name"></p>
  <p v-text="age"></p>
  <p v-text="name"></p>
</div>
<script>
  let data = {
    name: 'Xiaolan',
    age: 18,
    height: 180
  }
  // traverse each property  (data).forEach((key) => {
    // key attribute name    // data[key] attribute value    // data original object    defineReactive(data, key, data[key])
  })
  function defineReactive(data, key, value) {
    (data, key, {
      get() {
        return value
      },
      set(newVal) {
        // The data changes, the operation dom is updated        if (newVal === value) {
          return
        }
        value = newVal
        compile()
      }
    })
  }
  // Compile the function  function compile() {
    let app = ('app')
    // 1. Get all the sub-elements in the app    const nodes =    //  [text, input, text]
    //2. Iterate through all child elements    (node => {
      // nodeType is 1 for element node      if ( === 1) {
        const attrs = 
        (attrs).forEach(attr => {
          const dirName = 
          const dataProp = 
          ( dirName,dataProp)
          if (dirName === 'v-text') {
            (`Updated${dirName}instruction,The attributes that need to be updated are${dataProp}`)
             = data[dataProp]
          }
        })
      }
    })
  }
  // First rendering  compile()
</script>

The above is a detailed content for a deep understanding of the principle of two-way data binding in Vue. For more information about Vue’s two-way data binding, please pay attention to my other related articles!