zoukankan      html  css  js  c++  java
  • Vue双向数据绑定

    一、引入

      谈及Vue中的数据双向绑定,我们自然而然的想到是通过v-model指令实现的。但具体是怎么实现的呢?下面就介绍一下。

     

    二、v-model语法糖是什么?原理是什么?

      v-model语法糖是vue多个基础语法(属性绑定 和事件绑定)的简写。

      原理:给表单元素input绑定通过"v-bind:"绑定value属性的数据msg,再给表单元素input添加监听value值改变的事件@input,给msg重新赋值。

      代码:

    <!-- <input type="text" v-model="msg"> -->
    <input :value="msg" type="text" @input="msg=$event.target.value">

     

    三、双向数据绑定的原理?

      vue中数据双向绑定通过v-model实现,双向绑定指的是视图和内存中的数据进行双向绑定。(通过Object.defineProperty和给元素注册事件)

      表单元素改变数据的原理:

    • 实现数据驱动视图
    1. 需要先定义一个data对象将其中msg属性的值显示到视图中。想要通过Object.defineProperty来监测其值得变化是不可能实现的,因为使用他的同时需要给对象赋值并监听,而data对象中已经有了这个属性并绑定到了页面中显示,无法再重新定义该属性。这就需要新建一个空对象vm,通过给vm定义属性并监测来实现这个功能。
    2. Object.defineProperty调用时的第三个参数为对象配置项,其中的get()方法为vm的msg属性值被获取时触发的回调函数。set()方法为vm的msg属性值被设置时触发的回调函数,set()函数的参数为msg属性的新值。
    • 实现视图驱动数据

      通过给表单元素注册input事件,将表单元素中的value值赋给vue.msg

     <!-- 1. 把数据渲染到表单元素中 -->
      <!-- 2. 当你修改数据的时候,表单元素的值发生改变,视图需要更新 -->
      <!-- 3. 当你使用表单元素的时候,你在修改元素的值,对应的数据也要发生改变 -->
      <h5></h5>
      <input type="text">
      <script>
        // const vm = new Vue({data:{msg:'hi vue'}}) vm.msg = '数据'
        // 使用用定义可以监听(观察)的属性的。
        const vm = {}
        const data = { msg: 'hi vue' }
        // 获取dom
        const h5 = document.querySelector('h5')
        const input = document.querySelector('input')
        // 1. 默认渲染
        h5.innerHTML = data.msg
        input.value = data.msg
        // 2.1 监听 data中的msg的值改变  观察 data中的msg的值改变  最终监听的是vm的msg属性变化
        // 2.2 如果 数据改变  修改视图
        // 三个参数  给谁定义一个属性  属性的名称  对象配置项(get 获取属性值 set 设置属性值)
        Object.defineProperty(vm, 'msg', {
          get() {
            // 当获取msg属性值时触发
            // console.log('get')
            return data['msg']
          },
          set(newValue) {
            // 当设置msg属性值时触发
            // console.log('set')
            // console.log(newValue)
            // 数据改变
            data['msg'] = newValue
            // 修改视图
            h5.innerHTML = newValue
            input.value = newValue
          }
        })
        // 3. 监听 表单元素 的值改变事件  修改数据即可(上面已经实现数据驱动视图)
        input.oninput = function(){
          // console.log(this.value)
          vm.msg = this.value
        }
      </script>

      总体描述:

    • Vue内部会把data中的数据通过defineProperty方法转化为set和get的监控方式

    • 当data中的数据发生变化时,会触发对应的set或者get

      • 修改属性值的时候,触发set方法

      • 访问属性值的时候,触发get方法

    • 监控数据变化的目的还是为了更新页面(仅仅更新数据变化对应的DOM节点:尽可能少的更新DOM)

    • 但是完成上述要求需要底层虚拟DOM的支持

     

    四、什么是虚拟DOM?

      浏览器更新DOM比较耗时,为了节省时间,需要尽可能少的更新DOM。虚拟DOM是对真实DOM的一种描述;其组成部分虚拟节点也描述了真实的DOM节点,本质上就是普通对象

    // VNODE 虚拟节点:描述了真实的DOM节点,本质上就是普通对象
    {
        tagName: 'div'
        attrs: { class: "active", id: "info"}
        content: "hello"
    }
    • 虚拟DOM也会形成一个树状结构,描述了真实的DOM树(形成虚拟DOM树和真实DOM树的对应关系)

    • 如果数据发生变化,那么就会触发虚拟DOM数的对比(diff算法,过程发生在内存中)

    • 对比的结果是:有变化的虚拟节点的集合

    • 上述虚拟节点需要转化为真实的DOM节点(下面是虚拟下面是虚拟节点转换为真实节点的过程)

    var div = document.createElement(vnode.tagName)
    div.setAttibute(key, value)
    div.innerHTML = vnode.content
    
    • 最终会把真实的节点更新到页面

      双向数据绑定运用虚拟DOM的进一步解释说明:

        在使用defineProperty进行到set()时,会采用虚拟DOM来跟新视图;虚拟DOM有新、旧两份数据存储在内存中,每次监测到数据改变时,计算机会通过diff算法对比两份数据的区别,得到有变化的虚拟节点的集合,并将它们转换为真实的DOM节点更新到页面中。

        采用上面方式的原因就是浏览器解析完整DOM树的时间、性能消耗,要远比内存对比数据再进行局部渲染的消耗大得多。内存处理数据的速度要比浏览器快的多。

     

  • 相关阅读:
    Android中开发习惯
    Activity、Window和View三者间的关系有一定的见解
    Android底层有一定的认识,研究过相关的Android源码
    安卓工程的启动过程
    OAuth2认证有一定的了解
    屏幕适配经验
    NOIP模拟赛14
    NOIP模拟赛13
    NOIP模拟赛12
    NOIP模拟赛11
  • 原文地址:https://www.cnblogs.com/belongs-to-qinghua/p/11191537.html
Copyright © 2011-2022 走看看