关于vuejs mvvm原理

对于数据改变视图和视图改变数据是通过ViewModel这个中间层去实现的
但是看他的实现原理,网上都是介绍循环数据对象给他们加上Object.defineProperty
再经过wacther订阅者,最后由订阅者去通过视图更新,但是如果是视图的更新
怎么改变数据对象的值倒没有怎么提,有谁能说下这个原理吗?

阅读 5.3k
7 个回答

题主问改变数据,多数改变数据的操作是放在事件中做的。
当数据改变时,因为之前通过Object.defineProperty进行了数据绑定,所以会触发数据的setter,然后就按照如题所述的Dep->Watcher->_update->patch一步一步执行,最后经过patch得到差异然后将这些差异更新到视图上。

前阵子写过一系列Vue实现原理的文章,希望可以帮助到你。https://github.com/answershuto/learnVue

内部对v-modal属性的dom进行了onChange监听,onChange里面去更新了对应的modal

可以参考一下我前一段时间刚写的文章https://segmentfault.com/a/11...,最简单的vue数据双向绑定的实现,很短的一段代码,就是defineProperty 方法的使用,我使用的是Object.defineProperties,希望能帮到你。在线地址效果地址:http://www.sunzhaoye.com/demo...

把代码给你复制出来吧:

html代码:

<body>
    <p>
        input1=><input type="text" id="input1">
    </p>
    <p>
        input2=>
        <input type="text" id="input2">
    </p>
    <div>
        我每次比input1的值加1=>
        <span id="span"></span>
    </div>
</body>

js代码:

var oInput1 = document.getElementById('input1');
var oInput2 = document.getElementById('input2');
var oSpan = document.getElementById('span');
var obj = {};
Object.defineProperties(obj, {
    val1: {
        configurable: true,
        get: function() {
            return oInput1.value;
        },
        set: function(newValue) {
            // 过滤输入框的首尾空格
            newValue = newValue.replace(/(^\s*)|(\s*$)/g, "");
            oInput2.value = newValue;
            // 仅限输入数字,如果输入非Number类型, 则Number(newValue)为NaN了,只是为了说明计算属性,所以不做验证了
            // newValue为空时, Number(newValue) = 0
            // 输入0时, 是typeof newValue为String,为'0'
            // 以下代码是如果newValue为空, 判断条件为true, 如果newValue为'0',进入else 
            oSpan.innerHTML = Number(newValue) === 0 && newValue !=='0'  ? '' : Number(newValue)+1
        }
    },
    val2: {
        configurable: true,
        get: function() {
            return oInput2.value;
        },
        set: function(newValue) {
            // 过滤输入框的首尾空格
            newValue = newValue.replace(/(^\s*)|(\s*$)/g, "");
            oInput1.value = newValue;
            oSpan.innerHTML = Number(newValue) === 0 && newValue !=='0'  ? '' : Number(newValue)+1
        }
    }
});
oInput1.value = obj.val1;
oInput1.addEventListener('keyup', function() {
    obj.val1 = oInput1.value;   // val1赋值之后进入val1的setter
}, false);
oInput2.addEventListener('keyup', function() {
    obj.val2 = oInput2.value;   // val2赋值之后进入val2的setter
}, false);

我记得mvvm 是在基于mvc的基础上添加了指令 (也就是vue中的v-model , v-show )等, 进行双向数据绑定

其实就是在 dom 上监听事件,比如 input 标签上使用了 v-model 指令,那么在一开始的时候就会给 input 标签绑定 input 事件,对应的回调函数就是用来改变相应 data 的值

"双向数据绑定无非就是在单向绑定的基础上给可输入元素(input、textare等)添加了change(input)事件,来动态修改model和 view"——https://segmentfault.com/a/11...
刚看到一位大佬对双向绑定的解析,分享一波:https://ustbhuangyi.github.io...
很多同学在理解 Vue 的时候都把 Vue 的数据响应原理理解为双向绑定,但实际上这是不准确的,我们之前提到的数据响应,都是通过数据的改变去驱动 DOM 视图的变化,而双向绑定除了数据驱动 DOM 外, DOM 的变化反过来影响数据,是一个双向关系,在 Vue 中,我们可以通过v-model来实现双向绑定。

推荐问题
宣传栏