Backbone.js popover实现

时间:2013-07-07 09:50:17

标签: javascript jquery backbone.js

我是backbone.js的新手,我的第一个项目是实现一个可以轻松地在整个项目中重复使用的弹出视图。我定义了以下要求。

要求

  1. 弹出窗口应引用DOM中的另一个元素,以便能够计算弹出窗口的位置并打开/关闭弹出窗口。引用充当弹出切换按钮

  2. 一个新的popover附加到正文,关闭时popover被销毁并从DOM中删除

  3. 弹出窗口外的任何点击都会强制弹出窗口关闭并被销毁

  4. popover是一个骨干视图,它应该独立于它的父/创建者视图,开放/关闭等通信应该使用事件来执行

  5. 弹出内容可能是另一种观点

  6. 实施:

    首先,我创建一个将成为popover引用的视图:

    My.Views.Toggle = Backbone.View.extend({
        tagName: 'a',
        events: {
          'click': 'toggle'
        },
        serialize: function() {
          return { model: this.model };
        },        
        initialize: function() {          
          this.listenTo(this.model, 'change', this.render);
        },
        afterRender: function() {
          //here we should add the popover, right?
        },
        toggle: function(){  
          app.vent.trigger('my:navbar:toggle');
        }
    });
    

    在上述实施中,我们尊重要求#4。现在我们要考虑#1。为了能够为papover提供其父视图的引用,我们必须等到父视图完成呈现权限?所以我们必须在afterRender函数中创建popover:

    var popover = new Popover.Views.Default({ 
        content: "Hey there, I am a popover", 
        reference: this.$el
    });
    

    这个问题是它违反了要求#2。因为afterRender函数被调用两次,所以在模型更改之前和之后。每当模型再次更改时,也会调用此函数。所以DOM中会有很多popover实例。

    我的问题是,如何保证DOM中只有一个popover实例?

    My.Views.Popover = Backbone.View.extend({
        className: 'popover',
        initialize: function(options) {
          this.visible = false;
          this.content = options.content;
          this.reference = options.reference;
    
          app.vent.on('member:navbar:toggle', this.toggle, this);
    
          this.render();
        },
        afterRender: function() { 
          $('body').append(this.$el.append(this.content));
        },
        show: function() {
          this.visible = true;
          this.$el.show(); 
        },
        hide: function() {
          this.visible = false; 
          this.$el.hide();
        },
        toggle: function() {
          this.visible ? this.hide() : this.show();
        }
    });
    

    看起来像这样,但是有很多不足之处:

    enter image description here

1 个答案:

答案 0 :(得分:2)

我只会说我会做什么,因为这是一个非常自以为是的问题,

首先,应该有一个处理正文的主视图,即AppView({el:'body'}),正是这个视图应该提升你的应用程序并呈现将进入其中的所有视图。

其次,

afterRender: function() { 
  $('body').append(this.$el.append(this.content));
},

我认为视图应该只对它的创建负责。为了正确管理它,另一个视图应该是进行定位和管理的视图,除了当然包含主体的主视图,

My.Views.AppView = Backbone.View.extend({
  el: 'body',
  initialize : function(){
    this.popup = new Popover(...);
  },
  render : function(){
    this.titlebar.render()...
    this.content.render()...
    ...
    this.popup.render().appendTo(this.$el)...;
  }
});

我认为这给了我一个清晰的观点结构和他们的责任。