饥人谷技术博客让前端飞前端学习指南

Vue中的MVVM(2)--view -> model的绑

2018-03-01  本文已影响24人  大春春

再次看了上次写的博客关于Vue的MVVM,发现虽然介绍了MVVM的原理,但是感觉还不够详细,现在就再次根据这篇博客写详细一点,来看看new Vue的时候Vue究竟做了些什么事。
我想,以需求作为出发点来理解原理会比较容易,所以这篇博客会以提出需求 -> 解决需求的方式来写。

项目地址,欢迎start

Vue中的MVVM原理介绍

可以先阅读我的这篇博客了解一下关于Vue的MVVM,另外需要记住这一幅图(很重要),这张图就是本篇博客的概括:

image.png

回顾

继上一篇文章Vue中的MVVM--model -> view的绑定,我们完成了对页面的初始化渲染,达成了如下要求:

image.png
image.png
但还未完成view -> model的绑定,所以不能通过修改数据来触发视图的更新,今天就来完成剩余部分

提出需求

继上图:


image.png

我们需要做到的是:当修改输入框的数据时,上面的文字也随之进行刷新。

分析

先来看看还未完成的部分:

image.png
其中包含观察者Observer,监听器Watcher,然后还有一个Dep,过程是:
  1. Compiler中监听数据的变化并绑定监听器;
  2. 在观察者Observer中实现对所有数据的gettersetter
  3. 监听器Watcher把更新事件添加进Dep的事件队列中;
  4. 观察者Observer发现数据产生变化的时候通知Dep
  5. Dep把事件队列中的更新事件全部执行一遍;

总结下来就是实现两个事情:

  1. 添加数据依赖;
  2. 触发数据变更事件;
    接下来就先创建WatcherObserverDep三个类;
    image.png
    image.png
    image.png

先来看看Dep是什么

根据上面的的步骤描述,很容易感觉到Dep像是一个容器,存储着对视图的更新事件,是的,这是一个发布订阅模式的实现,该模式包含事件队列subs,添加事件方法addSub,执行事件队列函数notify,移除事件队列里的事件removeSub

image.png
看完发布订阅模式后,继续我们的流程。

添加依赖

  1. 更新视图的时候,我们先要获取当前的数据新值,然后作为参数放进回调函数中,并且还要对新的数据进行上面的依赖添加步骤,那么Watcher还需要一个update函数用来统一做这个事:
    image.png
  2. Observersetter中触发Depnotify方法,进行视图的更新:
    image.png
  3. 到了这步其实就已经达成效果了:


    image.png
  1. 当我们多次更新数据的时候,会发现添加进subswatcher发生了递增的现象,所以当快速更新数据时就会导致执行函数过多而页面崩溃;

    image.png
    造成这个现象的原因是在进行第一次的更新时,watcher将同一个数据的新值也进行了依赖添加,也就是let newVal = this.get()这一段;
    image.png
    既然知道了原因,那么解决起来也很简单,给每一个被监听的对象都添加一个id即可。
    因为添加sub的操作是在Watcher中进行的,所以在Watcher中创建一个对象depIds
    image.png
    然后给每一个Dep都添加一个不同的id
    image.png
    最后在Watcher中判断depIds是否已经有这个id的Dep实例存在,如果没有则添加进去并执行addSub,否则不执行:
    image.png
    效果,无论怎么修改,都只会有固定数量的Watcher存在:
    image.png
  2. 当修改数据为对象的时候,这个对象没有进行监听,这个也好解决,只要在setter中进行判断即可,若为对象则针对该对象重新进行监听

    image.png

总结

到这里为止,我们就完成了view -< model的绑定,并且知道在new Vue的时候大致做了一些什么事了,剩下的就是逐步完善,例如对更多指令的支持,对methods以及computedwatch的支持。

上一篇 下一篇

猜你喜欢

热点阅读