【问题标题】:Backbone.js: The right way to refactor view code?Backbone.js:重构视图代码的正确方法?
【发布时间】:2012-10-27 14:22:48
【问题描述】:

我想知道在哪里放置通用主干视图代码。例如,我的“NewPosts”视图中有以下内容:

  createPost: (event) ->
    #...
    @collection.create attributes,
      #...
      error: @handleError


  handleError: (entry, response) ->
    if response.status == 422
      #...

handleError 函数将在许多不同的视图中使用...我不确定最佳实践:将其放置在哪里。是否有一个相当于视图助手的主干,我可以把它放进去?还有其他攻击方式吗?

【问题讨论】:

    标签: javascript backbone.js coffeescript


    【解决方案1】:

    注意:我的 CoffeeScript 生锈了,所以我在 JS 中回答这个问题,但这个想法应该翻译。

    显然,解决这个问题的一种方法是给所有的视图一个父类,然后在该类中放置像 handleError 这样的方法。但是,如果您正在寻找一种更像“mixin”的添加方法的方式,您也可以这样做。

    Backbone 视图使用 extend 方法的参数进行初始化,如下所示:

    var MyView = Backbone.View.extend({
        someMethod: function(){ doSomething();}
    });
    

    这个论点并不神奇;它只是一个 JS 对象,因此您可以使用 _.extend 对其进行扩展,如下所示:

    var myCommonMethods = {
        handleError: function ...
    }
    
    var MyView = Backbone.View.extend(_({
        someMethod: function(){ doSomething();}
    }, myCommonMethods));
    

    这种方法的优点是您可以“混入”任意数量的方法集,而如果您使用父类,则会受到更多限制。父类方法虽然更简单:

    var BaseView = {
        handleError: function ...
    }
    
    var MyView = BaseView.extend({
        someMethod: function(){ doSomething();}
    });
    

    所以这真的取决于您的特定需求。

    就我个人而言,在我的代码中我使用了这两种方法:我有一个 BaseView,我的所有视图都可以扩展,并且我将非常常见的逻辑(比如我们的大多数视图使用的模板系统)放入其中。然后我有各种方法集的“混合”,这些方法集添加了额外的功能。

    例如,我为所有将“select”元素作为其 el 的视图混合了一组方法;这让这些视图有任何对它们有意义的基类,但仍然有一组通用的方法(例如,它们都有一个 selectOption 方法,可以让我在视图的 el 中为特定选项添加“selected”属性)。 希望对您有所帮助。

    【讨论】:

    • 不,但你的结果类会。从技术上讲,您正在做的是在扩展 Backbone.View 之前将混合组件与您的类的方法/属性相结合。所以,假设你做var myViewsMethods = {foo:whatever}; var MyView = Backbone.View.extend(_.extend(myViewMethods, mixin1, mixin2));。你最终会得到一份 Backbone.View 方法的副本,除了你的视图方法在它们之上,然后是 mixin1 的方法,以及 mixin2 的方法。如果所有四个对象都有一个“foo”方法,那么将使用 mixin2 中的“foo”方法。
    • (当然,mixin2 不一定要“王牌”;这一切都基于要扩展的参数的顺序,您可以根据需要重新排列参数;您可以说var myViewsMethods = {foo:whatever}; var MyView = Backbone.View.extend(_.extend({{}, mixin1, myViewMethods)); 这样,如果 mixin1 和您的视图方法都具有相同的方法,那么您视图中的方法将“胜过”。唯一棘手的部分是,如果您这样做,您需要包含一个空对象,就像我刚刚做的那样, 否则你最终会改变你的 mixin。)
    • 呃,刚刚注意到我在里面多了一个{;最后一个代码块应该是:var myViewsMethods = {foo:whatever}; var MyView = Backbone.View.extend(_.extend({}, mixin1, myViewMethods));
    【解决方案2】:

    您可以通过以下几种方式做到这一点: 使用这个方法定义一个基本视图,然后从这个视图而不是 Backbone.View 扩展所有其他视图

    var Base = Backbone.View.extend({
        handleError:function() {...}
    });
    
    var MyView = Base.extend({ ... });
    

    或者,使用帮助程序扩展现有视图

    var Helper = {
        handleError:function() {...}
    };
    
    var View1 = Backbone.View.extend({ ... });
    var View2 = Backbone.View.extend({ ... });
    $.extend(View1, Helper);    
    $.extend(View2, Helper);
    

    【讨论】:

      【解决方案3】:

      我将实现一个侦听事件的错误处理模型。您可以制作自己的自定义事件或使用默认值。我构建了一个大型复杂的backbone.js 应用程序,在我学会利用事件模型之前,它的架构非常困难。它节省了很多关注点之间的处理关系。

      创建一个事件调度器,并在初始化时将其作为参数传递给视图:

      类似这样的:

      var dispatcher = {};
      
      _.extend(dispatcher, Backbone.Events);
      
      dispatcher.on("event", function(msg) {
        // delegate to error handler
      });
      
      
      view = new View([dispatcher: dispatcher])
      view.dispatcher.trigger('event', {})
      

      我发现通过使用事件调度器,它隔离了我的视图、集合和模型,这使得测试变得非常容易。我可以在 chrome 的控制台中触发事件,然后观察各个组件是如何独立运行的。通过将调度程序暴露给记录器,它使调试变得更加容易并且我的代码更清晰。

      【讨论】:

        【解决方案4】:

        抱歉没有代码示例,但重构的概念之一是将通用代码移至基类,以便所有子类都可以重用代码。

        但我真的很喜欢 Rimian 的想法,即您的视图从对象或调度程序等事件源订阅错误事件。这将使您的所有视图彼此分离,并在收到错误事件时处理错误。

        【讨论】:

          猜你喜欢
          • 2011-07-03
          • 1970-01-01
          • 1970-01-01
          • 2015-10-04
          • 1970-01-01
          • 2013-06-30
          • 2012-09-19
          • 2017-05-02
          • 2010-09-16
          相关资源
          最近更新 更多