2

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

要求

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

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

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

  4. 弹出框是一个主干视图,它应该独立于它的父/创建者视图,应该使用事件执行诸如打开/关闭之类的通信

  5. Popovers 内容可能是另一个视图

实施:

首先,我创建一个将作为弹出框引用的视图:

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 函数中创建弹出框:

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();
    }
});

看起来像这样,但是有许多底层弹出窗口:

在此处输入图像描述

4

1 回答 1

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)...;
  }
});

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

于 2013-07-07T17:16:06.643 回答