数据驱动应该是从flux/redux
+ react
这种模式开始流行的。 react
他的背后不只仅是数据驱动这么简单,在复杂的系统中,我以为它解决了一个很关键的问题就是模块间的交互/通讯。有不少文章拿他和mvc/mvvm去比较,我我的以为没有特别的可比性,由于解决的问题不一样。git
一个稍微复杂点的例子: github
假若有这么一个页面,咱们按照以往模式开发,首先模块化开发,拆分红A,B,C 三个模块,而后每一个模块有本身的子模块。 redux
若是需求简单还比较好解决,每一个模块中本身解决本身的逻辑,解耦的很是清晰。父子之间的关系也很是明确。微信
例如销毁C模块
,会自动销毁它的子模块C1
和C101
。数据结构
模块间的关系也很清晰,B1
不会和B2
有直接关系,他们之间须要经过B模块
去传递。同理,B模块
和A模块
也没有直接关系,他们都须要经过外层页面
去处理关系。mvc
可是假若有这么一个需求,A2
的显示和B2
(用户交互)以及C101
(用户交互)相关怎么办。mvvm
按照这种模式,它的解决方案是: 模块化
B2
若是发生改变,通知B模块
,B模块
在通知页面
,页面
调用A模块
和C模块
,C模块
调用C1
,C1
调用C101
获取C101
的数据处理,页面
调用A模块
,A模块
再调用A2
,再结合一下从C101
获取的数据,改变它的展现。 spa
是否是看着很绕,从图上看是这么个关系:
图中仅仅显示了其中一个复杂交互,假如咱们再多两个模块间关联的逻辑:
B1
和B2
模块影响A2
模块(图中黄线)
C1
影响B1
模块(图中白线)
以下图:
3个复杂一点的交互,整个模块间的通讯已经变成蜘蛛网了,重要的是,每一条关系线都须要开发者维护的,不只影响开发效率,并且很差维护,容易引起bug,假如后期加新需求或者调整需求,开发成本都是比较高的。
可见,对于复杂的交互,或者模块间关系复杂时,这种依赖父子关系的通讯,是一个很大的障碍。
可是咱们怎么办,拒绝模块化开发吗?那样页面设计起来耦合度更大,更加不可维护。
首先一点,模块化开发是一个不可逆的趋势,然而在这种趋势下,解决模块化通讯是一个很是重要的点。
在那个时候,我考虑最多的就是如何去解决模块之间的通讯,如何让模块之间交互更加轻松,模块之间更加独立。
当时考虑的一个方案是使用一个全局的event(全局的on和fire)。这样模块之间就不用依赖父子关系了。模块和模块间是能够之间交互的。
可是这样会有一些弊端:
事件名称如何定义,保证不重名
事件是否会重复的on
模块和模块之间会由于事件产生一些耦合
当交互特别复杂时,也会比较麻烦,仍是上面的例子,B2
通知C2
改变后,C2
还须要通知C101
获取一次数据,来确认改变
总体来看:
优点: 摆脱了模块间父子层级关系,能够简单的跨模块通讯
劣势: 依然须要维护复杂的模块间关系,只是能够绕过父子依赖
全局共享一个model + component模式。这种其实已经很是趋向与数据驱动了。每一个模块都是共享全局的model,而后每一个component均可以被全局获取到到,里面的功能属性能够直接被使用。
其实这种模式已经比较理想,页面上面的任何component均可以被直接调用到而且使用。
我的以为缺点就是:
多了一个全局可调用component的功能。若是砍掉他能够实现完成数据驱动,若是模块调用时,使用多了直接获取component的功能,仍是须要在模块间维护好和其余模块间的交互逻辑。
先看一个图,我感受能够很好的体现数据驱动
提线木偶:他的特色就是每一个动做都是,头,手臂,脚,金箍棒都是由操做的人手决定的,头和手臂直接没有任何关系。
数据驱动也能够这么理解,页面上面因此的展现都是由数据决定的,和页面其余地方没有任何关系。
再来看看上面那个例子若是加上数据驱动的设计思想。
页面之间每一个模块,不用关心父子模块之间的关系,每一个独立的模块都是由一个全局的model决定。
回到上面那个麻烦的场景。当B2
改变时,它会修改model中对应的数据(效验C101数据,结合B2的改变,修改A2的数据),而后A2的业务模块跟进A2的数据改变。
这种设计的核心是每个模块的改变,所有都交给model处理。
而后model里面会和个个模块一一对应,每一个模块无需关注其余模块的变化,只须要关注model里面对应本身数据的变化便可。因此模块间关系链条会显得很是简单。
重点在于,当交互逻辑不断增长时,这个关系链条依然不会增长,由于模块只和model里面对于的数据相关联。
固然,这种模式也没法去省略复杂的业务逻辑,只是业务逻辑所有都会汇集在model中。能够理解为页面上全部的操做都是对数据的操做。而后每一个模块只须要监听关注的数据改变便可,这个监听关系就是图中惟一的一条关系线。
换一个理解,咱们将直接的模块和模块直接的耦合关系所有转移到了数据中去体现。而数据的维护是远远比模块更好维护的。
仍是上面页面为例子:
model
var page = { a: { isShow: true, children: [{ a1: { isShow: true } }, { a2: { isShow: true } }] }, b: { isShow: true, children: [{ b1: { isShow: true } }, { b2: { isShow: true } }] }, c: { isShow: true, children: [{ c1: { isShow: true, children: [{ c101: { isShow: true } }] } }] } }
isShow 表示展现的意思。这个状态对应文章第一个图片。
当数据改变时,例如model发生变化以下:
var page = { a: { isShow: true, children: [{ a1: { isShow: true } }, { a2: { isShow: false } }] }, b: { isShow: true, children: [{ b1: { isShow: true } }, { b2: { isShow: false } }] }, c: { isShow: true, children: [{ c1: { isShow: false, children: [{ c101: { isShow: true } }] } }] } }
对应下面这样:
换一个理解就是每一种数据状态对应一种页面的展现状态。页面想展现成什么样子,须要数据处理成什么样子。数据是这个页面的核心。
第一点数据结构的处理,由于数据决定了整个页面的展现,数据结构开始的设计很是关键,数据结构的可扩展性决定了页面的可扩展性,若是开始数据模式很差,后期维护也会很是难受。
第二点是处理好模块和数据中对应的关系。
能够看到数据驱动的难点和关键点就是数据结构的设计。而这个也是很考验开发者能力的。数据结构的好坏直接决定了后期业务开发的质量。
文章开头说了,从个人角度理解数据驱动这种模式和mvc并无什么竞争关系,在具体的实践中,每个模块能够是一个mvc或者mvvm,模块的内部处理交给模块本身,能够是mvc,或者单例也能够。数据驱动主要是处理模块之间的一种逻辑。
那么为何数据驱动和react这种结合的更加好了?由于react更进一步是讲模块内部也实现一个数据驱动,模块内部的数据改变了,模块的状态会跟着改变。