vue双向数据绑定的原理

628 阅读2分钟

vue框架出现之初,就以mvvm模式,双向绑定让人眼前一亮,同样的,从开始使用vue,vue双向绑定的原理也一直是面试的高热话题,那么我们今天来聊聊关于双向数据绑定原理。

MVVM

首先要聊的是MVVM,在这个概念之前,我们经历过最对的应该是MVC,也就是模型,视图,控制器,就是把一次数据渲染看出是由控制器指挥的从模型到视图的过程,在这个基础上,我们再看MVVM,为了理解他是这样读的,MVVM,也就是说是三部分,M依然是模型,V依然是视图,但是VM是一个整体,就是视图模型,作为前端小伙伴,编写代码的过程当中可以把所有业务逻辑放到这个VM层当中。基于上面的描述,我们总结:

1、MVVM也是一种类似MVC的设计模式。

2、M是模型代表的是数据,vue是视图,在前端代表展示的UI层(有后端基础的小伙伴一定要注意这个区分,这里并不是视图函数),而VM这是视图模型,通过他来讲M的数据渲染到V上面。

3、M和V不会直接沟通,M会直接国通VM,并且是双向的,同样VM还会沟通V,所以我们了解MVVM或者双向绑定,还是需要侧重在VM这个概念上。

4、作为中间的传输工具,VM必须知道M和V任何一个的变化,并且可以通知到另一端。

image.png

Object.defineProperty

上面聊了大概的概念,那么下面来聊聊实现双向绑定的核心

js当中的Object.defineProperty(obj, prop, descriptor) 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象,其中参数:

obj:要定义属性的对象

prop:要定义或修改的属性的名称或 Symbol

descriptor:要定义或修改的属性描述符

返回值:被传递给函数的对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>双向绑定</title>
</head>
<body>
    <input type="text" id="app">
    <span id="text"></span>
</body>
<script>
    var obj = {};
    var init_value='a'; //这里一定要用var
    Object.defineProperty(obj,'init_value',{
        get(){ // 获取值的时候触发
​
            console.log('获取obj最新的值');
            return init_value
        },
        set(new_value){ // 设置值的时候触发
            init_value = new_value;
            console.log('设置最新的值');
            document.getElementById('text').innerHTML = init_value;
            console.log(obj.initValue);
        }
    });
    //这里和双向绑定的关系已经不是很大了,只是一个监听事件,当文本框里面的值发生修改
    // 获取最新的值 然后赋值给obj
    document.addEventListener('keyup', function (e) {
        obj.init_value = e.target.value;
    })
​
</script>
</html>

总结

那么回头来总结,在vue当中也是如此,先将vue当中的初始值渲染到页面上,然后如果页面上数据发生修改,在同步到vue实例当中,然后如果vue实例当中的数据发生了变化再同步回来。这个过程就是js当中的数据劫持。

当然vue再实现双向绑定的过程当中,除了上面的数据劫持还使用了很多技术,比如DocuemntFragment 拦截,发布订阅模式等等,我们之后再做详细的解释,这里还是欢迎各位大佬多多指定。