Vue 响应式 / 双向数据绑定

一、关于双向数据绑定

  • 数据模型和视图之间的双向绑定

  • Vue 中的 MVVM

  • 通常,我们需要编写代码,将从服务器获取的数据进行“渲染”,展现到视图上。每当数据有变更时,我们会再次进行渲染,从而更新视图,使得视图与数据保持一致。也就是:


    model-view.png
  • 而另一方面,页面也会通过用户的交互,产生状态、数据的变化,这个时候,我们则编写代码,将视图对数据的更新同步到数据,以致于同步到后台服务器。也就是:


    view-model.png
双向数据绑定
  • 当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化;可以这样说用户在视图上的修改会自动同步到数据模型中去,数据模型也是同样的变化


    model-view-mode.png
  • 双向数据绑定的优点:无需和单向数据绑定那样进行 CRUD(Create,Retrieve,Update,Delete)操作,双向数据绑定最常应用在就表单上,这样当用户在前端页面完成输入后,不用任何操作,我们就已经拿到了用户输入好的数据,并放到数据模型中了

二、双向数据绑定的实现

v-model 实现双向数据绑定
  • v-model 是一个 value 绑定加 input 事件回调的语法糖

// 等价于

三、双向数据绑定的原理

  • Object.defineProperty()
    方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
  • Proxy
    对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)
  • Reflect
    是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与proxy handlers的方法相同。Reflect不是一个函数对象,因此它是不可构造的
2.0 版

  • 缺点:
    • 在 Vue 中,Object.defineProperty 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。 为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组 push() pop() shift() unshift() splice() sort() reverse()
    • Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 里,是通过递归以及遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象,不管是对操作性还是性能都会有一个很大的提升
3.0版
    let defineObject = {
        userInfo: {
            userName: '',
            password: '123456'
        }
    }
    let input = document.getElementById('userName')
    let view = document.getElementById('view')

    // 更新视图
    function update(newValue) {
        view.innerText = newValue
    }
    //更新数据
    input.oninput = function () { 
        newProxy.userName = this.value
    }

    let newProxy = new Proxy(defineObject, {
        get(target, key, receiver) {
            console.log('getProp: ', target[key])
            return Reflect.get(target, key);
        },
        set(target, key, newValue, receiver) {
            console.log('setProp: ', target[key])
            if(key === 'userName') {
                update(newValue)
            }
            return Reflect.set(target, key, newValue)
        }
    });

三、思考的问题

1、Vue 为什么不能检测数组变动

你可能感兴趣的:(Vue 响应式 / 双向数据绑定)