@@ -493,6 +493,123 @@ function registerAction (store, type, handler, local) {
493
493
}
494
494
```
495
495
496
- dispatch
496
+ 因为registerAction的时候将push进_actions的action进行了一层封装(wrappedActionHandler),所以我们在进行dispatch的第一个参数中获取state、commit等方法。之后,执行结果res会被进行判断是否是Promise,不是则会进行一层封装,将其转化成Promise对象。dispatch时则从_actions中取出,只有一个的时候直接返回,否则用Promise.all处理再返回。
497
497
498
- 因为registerAction的时候将push进_actions的action进行了封装
498
+ ### watch
499
+
500
+ ``` javascript
501
+ /* 观察一个getter方法 */
502
+ watch (getter , cb , options ) {
503
+ if (process .env .NODE_ENV !== ' production' ) {
504
+ assert (typeof getter === ' function' , ` store.watch only accepts a function.` )
505
+ }
506
+ return this ._watcherVM .$watch (() => getter (this .state , this .getters ), cb, options)
507
+ }
508
+ ```
509
+
510
+ 熟悉Vue的朋友应该很熟悉watch这个方法。这里采用了比较巧妙的设计,_ watcherVM是一个Vue的实例,所以watch就可以直接采用了Vue内部的watch特性提供了一种观察数据getter变动的方法。
511
+
512
+ ### registerModule
513
+
514
+ ``` javascript
515
+ /* 注册一个动态module,当业务进行异步加载的时候,可以通过该接口进行注册动态module */
516
+ registerModule (path , rawModule ) {
517
+ /* 转化称Array */
518
+ if (typeof path === ' string' ) path = [path]
519
+
520
+ if (process .env .NODE_ENV !== ' production' ) {
521
+ assert (Array .isArray (path), ` module path must be a string or an Array.` )
522
+ assert (path .length > 0 , ' cannot register the root module by using registerModule.' )
523
+ }
524
+
525
+ /* 注册*/
526
+ this ._modules .register (path, rawModule)
527
+ /* 初始化module*/
528
+ installModule (this , this .state , path, this ._modules .get (path))
529
+ // reset store to update getters...
530
+ /* 通过vm重设store,新建Vue对象使用Vue内部的响应式实现注册state以及computed */
531
+ resetStoreVM (this , this .state )
532
+ }
533
+ ```
534
+
535
+ registerModule用以注册一个动态模块,也就是在store创建以后再注册模块的时候用该接口。内部实现实际上也只有installModule与resetStoreVM两个步骤,前面已经讲过,这里不再累述。
536
+
537
+ ### unregisterModule
538
+
539
+ ``` javascript
540
+ /* 注销一个动态module */
541
+ unregisterModule (path ) {
542
+ /* 转化称Array */
543
+ if (typeof path === ' string' ) path = [path]
544
+
545
+ if (process .env .NODE_ENV !== ' production' ) {
546
+ assert (Array .isArray (path), ` module path must be a string or an Array.` )
547
+ }
548
+
549
+ /* 注销*/
550
+ this ._modules .unregister (path)
551
+ this ._withCommit (() => {
552
+ /* 获取父级的state */
553
+ const parentState = getNestedState (this .state , path .slice (0 , - 1 ))
554
+ /* 从父级中删除 */
555
+ Vue .delete (parentState, path[path .length - 1 ])
556
+ })
557
+ /* 重制store */
558
+ resetStore (this )
559
+ }
560
+ ```
561
+
562
+ 同样,与registerModule对应的方法unregisterModule,动态注销模块。实现方法是先从state中删除模块,然后用resetStore来重制store。
563
+
564
+ ### resetStore
565
+
566
+ ``` javascript
567
+ /* 重制store */
568
+ function resetStore (store , hot ) {
569
+ store ._actions = Object .create (null )
570
+ store ._mutations = Object .create (null )
571
+ store ._wrappedGetters = Object .create (null )
572
+ store ._modulesNamespaceMap = Object .create (null )
573
+ const state = store .state
574
+ // init all modules
575
+ installModule (store, state, [], store ._modules .root , true )
576
+ // reset vm
577
+ resetStoreVM (store, state, hot)
578
+ }
579
+ ```
580
+
581
+ 这里的resetStore其实也就是将store中的_actions等进行初始化以后,重新执行installModule与resetStoreVM来初始化module以及用Vue特性使其“响应式化”,这跟构造函数中的是一致的。
582
+
583
+ ## 插件
584
+
585
+ Vue提供了一个非常好用的插件[ Vue.js devtools] ( https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd )
586
+
587
+ ``` javascript
588
+ /* 从window对象的__VUE_DEVTOOLS_GLOBAL_HOOK__中获取devtool插件 */
589
+ const devtoolHook =
590
+ typeof window !== ' undefined' &&
591
+ window .__VUE_DEVTOOLS_GLOBAL_HOOK__
592
+
593
+ export default function devtoolPlugin (store ) {
594
+ if (! devtoolHook) return
595
+
596
+ /* devtoll插件实例存储在store的_devtoolHook上 */
597
+ store ._devtoolHook = devtoolHook
598
+
599
+ /* 出发vuex的初始化事件,并将store的引用地址传给deltool插件,使插件获取store的实例 */
600
+ devtoolHook .emit (' vuex:init' , store)
601
+
602
+ /* 监听travel-to-state事件 */
603
+ devtoolHook .on (' vuex:travel-to-state' , targetState => {
604
+ /* 重制state */
605
+ store .replaceState (targetState)
606
+ })
607
+
608
+ /* 订阅store的变化 */
609
+ store .subscribe ((mutation , state ) => {
610
+ devtoolHook .emit (' vuex:mutation' , mutation, state)
611
+ })
612
+ }
613
+ ```
614
+
615
+ 如果已经安装了该插件,则会在windows对象上暴露一个__ VUE_DEVTOOLS_GLOBAL_HOOK__ 。devtoolHook用在初始化的时候会触发“vuex: init ”事件通知插件,然后通过on方法监听“vuex: travel-to-state ”事件来重置state。最后通过Store的subscribe方法来添加一个订阅者,在触发commit方法修改mutation数据以后,该订阅者会被通知,从而触发“vuex: mutation ”事件。
0 commit comments