【问题标题】:routing backbone apps when using mediator pub/sub patterns使用中介发布/订阅模式时路由主干应用程序
【发布时间】:2023-03-19 19:25:01
【问题描述】:

我正在主干中构建一个应用程序,它结合了来自https://github.com/addyosmani/backbone-aura/ 的模块化和外观/中介 pub/sub 模式,以在模块之间发送消息,以保持干净的代码库。

在 aura 的整个应用示例中寻找 Router,我发现只有自述文件描述了路由器作为模块本身的一部分的理想用途:“在 Backbone.js 术语中,小部件由模型、视图、集合组成和路由器以及小部件呈现所需的任何模板。”

所以我尝试了多种解决方案来实现可扩展的路由系统(可扩展的意思是模块可以指定自己的子路由),包括一个接受消息set-route 来设置路由的路由器模块,以及监听@987654324 的模块@ 信息。我还为每个模块使用了一个子路由器。问题似乎是在初始页面加载时,由于消息传递的“异步”性质,路由及其回调可能未在全局路由器解析 URL 时定义。您可以想象我可能需要在启动路由器模块之前对所有消息进行排队。

我想实现一些干净的东西,这是有道理的。我也在考虑可能首先解析所有小部件的所有路由,然后实例化路由器,这使得路由器模块成为一种特殊情况,因此不应该成为模块的一部分。

路由器应该是一个使用消息的模块,还是应该是一个扩展,或者是模块可以访问的全局架构的某个更高阶的部分?

我知道这是一个加载的问题,提前感谢您的帮助!

【问题讨论】:

    标签: javascript backbone.js publish-subscribe router mediator


    【解决方案1】:

    关于这个问题有很多争论,我认为很多争论源于我对路由器正式称为控制器的混淆。当我去年底开始使用 Backbone 时,已经做出了改变,但我相信很多人已经围绕路由器作为控制器构建了应用程序。我从来不同意这一点。对我来说——依赖于在 Backbone 创建之前很久就构建了类似于 Backbone 的专有 MVC 引擎的经验——路由器只是一个历史管理器组件。

    因此,要解决您在决定如何最好地实施路由器时遇到的特定问题,请考虑以下几点:

    1. 首先,路由器不是应用程序的必要组件。您可以在没有路由器的情况下仍然导航到应用程序的各个页面或屏幕。
    2. 路由器不是控制器,因为它的主要功能是管理历史。尽管您可以在路由器中嵌入应用程序业务逻辑,但我总是发现这会混淆路由器的实际功能。
    3. 通过使路由器成为应用程序的组件,您可以更好地分离关注点,并且可以拥有更有效的发布/订阅类型的安排。

    以下是我在应用程序中使用的路由器模块的代码,它遵循调解器、发布/订阅模式:

    /**
     * The idea behind this component is simply to relegate Backbone.Router to
     * doing what it does best: History Management. All it is responsible for
     * is two things:
     *
     * 1. Update the URL if router.navigate is invoked
     * 2. Trigger a routeChanged event if the URL was updated either by a bookmark or
     *    typed in by a user.
     */
    define(function () {
        return Backbone.Router.extend({
            initialize : function (map) {
                this._reversedMap = this.reverseModuleMap(map);
            },
            routes:{
                '*actions':'notify'
            },
            notify:function (actions) {
                var args = arguments;
                this.trigger("routeChanged", {command:actions});
            },
            /**
             * Override Backbone.Router.navigate. Default is to pass a router fragment, but for
             * our uses, we'll translate the "route" into a module mapping so that the controller
             * will know which module to display.
             * @param param
             * @param options
             */
            navigate:function (param, options) {
                //console.log('navigate', param);
                if(!param.suppressNavigate && param.actionCommand)  {
                    Backbone.Router.prototype.navigate.call(this, this._reversedMap[param.actionCommand]);
                } else if(!param.actionCommand) {
                    Backbone.Router.prototype.navigate.call(this, param, options);
                }
            },
            /**
             * this function simply reverses the key and value of the "map"
              * @param map
             */
            reverseModuleMap:function (map) {
                var newMap = {};
                _.each(map, function (value, key) {
                    newMap[value] = key;
                });
                // reversed key and value
                return newMap;
            }
        });
    });
    

    然后,当我实例化组件时,我向它传递一个映射,以便我的控制器知道要导航到哪个模块:

    this._router = new Router({
        _default: 'moduleA',
        sites : 'moduleA',
        apps : 'moduleB'
    });
    this._router.on('routeChanged', this.handleRouteChange, this);
    

    我发现它最重要的一点是它使代码保持美观和简单,并允许我专注于控制器中的业务逻辑。

    【讨论】:

      猜你喜欢
      • 2021-09-09
      • 1970-01-01
      • 2012-04-06
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多