-
Notifications
You must be signed in to change notification settings - Fork 761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
探秘 vue-rx 2.0 #39
Comments
能否将Rxjs理解为是比Vuex更好的一种数据管理的选择? |
不能简单评价好不好,而是复杂场景下更合适
发自我的 iPhone
在 2016年12月14日,下午5:08,limichange <[email protected]<mailto:[email protected]>> 写道:
能否将Rxjs理解为是比Vuex更好的一种数据管理的选择?
―
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub<#39 (comment)>, or mute the thread<https://github.com/notifications/unsubscribe-auth/ACmVJ0EkReL1Z0iED_4C691HiSK5niZ6ks5rH7IFgaJpZM4Kuqry>.
|
请问使用vue-rx兄弟间组件数据共享有没有好的实践? |
@gengjiawen 兄弟间组件数据共享和 vue-rx并没有直接关系, 可以把Observable提到比组件更高的层级,组件去subscribe 就好了 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
前一段时间,我写了两篇文章,一篇是对目前前端主流视图框架的思考:#37,一篇是深入使用RxJS控制复杂业务逻辑的:#38,在这两篇中,我分别提到:
最近,VueJS社区升级了vue-rx这个库,实现了比较方便地把VueJS和RxJS结合的能力。
我们来详细了解一下。
在视图上绑定Observable
VueJS本身不是基于RxJS这一套理念构建的,如果不借助任何辅助的东西,可能我们会需要干这么一些事情:
在业务开发中,我们最常用的是绑定简单的Observable,在vue-rx中,这个需求被很轻松地满足了。
与早期版本不同,vue-rx 2.0在Vue实例上添加了一个subscriptions属性,里面放置各种待绑定的Observable,用的时候类似data。
比如,我们可以这么用它:
rx-simple.vue
这个demo里面,演示了四种不同的Rx数据形态。其中,
single$
和interval$
虽然创建方式不同,但实际上用的时候是一样的,因为,对它们的订阅,都是取其最后一个值,这两者的区别只是,一个不变了,一个持续变,但界面展示的始终是最后那个值。关于数组,初学者需要稍微注意一下,从同样的数组,分别通过Observable.of和Observable.from出来的形态是大为不同的:
那么,这个
high$
代表什么呢?如果说不mergeAll,直接订阅map出来的那个二阶流,结果是不对的,vue-rx只支持一阶订阅绑定,不支持把高阶流直接绑定,如果有业务需要,应当自行降阶,通过各种flat、concat、merge操作,变成一阶流再进行绑定。
将Vue $watcher转换为Observable
上面我们述及的,都是从Observable的数据到Vue的ReactiveSetter和Getter中,这条路径的操作已经很简便了,我们只需把Observable放在vue实例的subscriptions里面,就能直接绑定到视图。
但是,反过来还有一条线,我们可能会需要根据某个数据的变化,让这个数据进入一个数据流,然后进行后续运算。
例如:有一个num属性,挂在data上,还有一个数据num1,表达:
始终比num大1
这么一件事。当然,我们是可以直接利用computed property去做这件事的,为了使得我们这个例子更有说服力,给它这个加一计算添加一个延时3秒,强行变成异步:
始终在num属性确定之后,等3秒,把自己变成比num大1的数字
。这样,computed property就写不出来了,我们可能就要手动去
$watch
这个num,然后在回调方法中,去延时加一,然后回来赋值给num1。在vur-rx中,提供了一个从
$watch
创建Observable的方法,叫做$watchAsObservable
,我们来看看怎么用:rx-watcher.vue
这个例子里面的num$经过这么几步:
this.$watchAsObservable('num')
,把num属性的变动,映射到一个数据流上$watch
不到的,所以,用startWith,把当前值放进去那么,这件事的原理是什么呢?
我们知道,Vue实例中,data上的属性都会存在ReactiveSetter,所以它被赋值的时候,就会触发这个setter,所以,
$watchAsObservable
的内部只需根据数据变动,生成一个Observable就可以了。$watchAsObservable
的方法签名如下:这个options,跟vue的
$watch
方法的options一样。有时候,我们会有这样的情况:在组件实例化的时候,数据流由于缺少某些条件,可能还没法创建。
比如说,某个组件,依赖于路由上面的某个参数,这时候,可能你不知道怎么去初始化绑定。
其实,产生这样的想法,本身就错了,因为没有用Rx的理念去思考问题。想一下下面这句话:
数据流的定义,与初始条件是否具备无关。
初始条件其实也只是整个数据流管道中的一节,如果初始不确定的话,我们只要给它留一个数据入口就好了,后续的流转定义可以全部写得出来。
然后,在路由变更等事件里,往这个
taskId$
里面next当前的id就可以了。通过这种方式,我们就可以把task$
直接绑定到界面上。或者,
taskId$
也可以通过在路由上面的watch转化而成,只是不能直接用$watchAsObservable
,可以考虑改进一下这种情况。这样可以实现组件canReuse的情况下,改动路由参数,触发当前页面的
数据刷新
,实现视图的更轻量级的刷新。将DOM事件转化为Observable
使用RxJS可以直接把DOM事件转化为Observable,vue-rx也提供了一个类似的方法来做这个事,不过我没理解这两个东西有什么差异?具体参见官方示例吧。
构建优化
关注vue-rx的readme,可以发现,目前推荐使用绑定的方式是这样:
但这样会有一个问题,import的是rxjs/Rx,我们看到,这个文件里把所有可以被挂接到Rx对象上的东西都import进来了,这会导致构建的时候没法tree-shaking,用不到的那些操作符也被构建进来了,一个简单的demo,可能构建结果也有200多k,这还是太大了。
我们查看一下vue-rx的源码,发现传入的这个Rx是怎么使用的呢?
这里,其实只是要使用Observable和Subscription这两个东西,所以我们可以改成这样:
再试试,构建大小只有不到100k了,而且是可以正常运行的。如果用的是Rx 4,需要传入的就是Disposable而不是Subscription。
另外,如果我们使用了
$watchAsObservable
,还会需要引入另外一个东西:这是因为在
$watchAsObservable
里面,为了共享Observable,把它pubish之后refCount了,所以要引入,用不到这个方法的话,可以不引。如果使用了
$fromDOMEvent
,还需要引入这个:因为
$fromDOMEvent
里面的这段:小结
有了这个库之后,我们就可以比较优雅地结合VueJS和RxJS了。之前,两者之间结合的麻烦点主要在于:
在RxJS体系中,数据的进、出这两头是有些繁琐的。
所以,CycleJS采用了比较极端的做法,把DOM体系也包括进去了,这样,编写代码的时候,数据就没有进出的成本,但这么做,其实是牺牲了一些视图层的编写效率。
而Angular2中,用的是async这个pipe来解决这问题,这也是一种比较方便的办法,在绑定Observable这一点上,跟有了vue-rx之后的Vue是差不多简便的。
React体系里面也有对RxJS的适配,而且还有跟Redux,Mobx对接的适配,感兴趣的可以自行关注。
从个人角度出发,vue-rx这次的升级很好地满足了我对复杂应用开发的需求了。
本文示例代码参见:这里
The text was updated successfully, but these errors were encountered: