如何在Marionette.js中使用modelEvents

时间:2013-11-09 07:12:59

标签: javascript backbone.js marionette

我有2个id为source,destination的文本字段。如果任何字段值发生更改,则相应的模型属性将更改。我使用Backbone.Model and events object in Marionette.CompositeView做了这个。它工作正常。

一旦任何模型属性改变相应的函数将调用。为此我写了以下代码。它不起作用问题是即使一个属性改变了两个函数都在评估。

型号代码:

var mapModel = Backbone.Model.extend({
  defaults: {
    startPlace: "",
    endPlace: ""
  }
});

Marionette.CompositeView代码:

var mapView = Marionette.CompositeView.extend({
  events: {
    "blur #source": "sAttributeSetting",
    "blur #destination": "dAttributeSetting"
  },

  dAttributeSetting: function() {
    this.model.set({"endPlace": document.getElementById(this.ui.destinationPlace).value});
  },

  sAttributeSetting: function() {
    this.model.set({"startPlace": document.getElementById(this.ui.sourcePlace).value});
  },

  modelEvents: {
    "change startPlace": "startMarkerDisplay",
    "change endPlace": "endingMarkerDisplay"
  },

  startMarkerDisplay: function() {
    alert("start");
  },

  endingMarkerDisplay: function() {
    alert("end");
  }
});

html代码:

<input type="text" id="source">
<input type="text" id="destination">

为模型和视图创建实例

mapModelObj = new mapModel();
var mapViewObj = new mapView({el:$('#mapDiv'), model:mapModelObj});

问题:

  1. 最初如果我在第一个字段(来源)中输入任意值,获得2个警告框(“开始”,“结束”)。

  2. 最初如果您在第二个字段(目标)中输入任意值,则会收到4个警告框(“开始”,“结束”,“开始”,“结束”)

  3. 我尝试了很多,但我不明白我在哪里遇到问题

    任何人都可以帮助我。

    由于

2 个答案:

答案 0 :(得分:3)

modelEvents应通过:连接。比如说,更改startPlace的事件应该是

'change:startPlace'

如果您使用空格,您将以两个事件结束,而不是一个特定于此属性的事件。

您的代码'change startPlace'代表两个事件,一个是“更改”,另一个是“startPlace”。所以你会看到“开始”,“结束”,“开始”,“结束”

答案 1 :(得分:0)

我的观察结果如下(但我建议 第二解决方案在底部):

  • 实体事件的绑定具有冒号语法。它应该是{ "event:name": "eventHandler" }配置的哈希值。多个处理程序可以用空格分隔。可以提供函数而不是字符串处理程序名称。

  • 您可以利用骨干视图的el属性。 您可以使用document.getElementById(this.ui.sourcePlace),而不是使用this.$('#source')。这最新搜索仅在el的上下文中搜索,而不是搜索整个dom。这样评估会更快......这样你应该使用这个表达式:this.$('.destination').val()

请检查我的问题:http://jsfiddle.net/orbanbotond/VEcK6/

代码如下:

var mapModel = Backbone.Model.extend({
  defaults: {
    startPlace: "",
    endPlace: ""
  }
});

var mapView = Marionette.CompositeView.extend({
  events: {
    "blur .source": "sAttributeSetting",
    "blur .destination": "dAttributeSetting"
  },
  dAttributeSetting: function(){
    console.log('end blured');
    console.log('input value:' + this.$('.destination').val());
    this.model.set({
      "endPlace": this.$('.destination').val()
    });
    console.log('endplace set to: ' + this.model.get('endPlace'));
  },
  sAttributeSetting: function() {
    console.log('start blured');
    console.log('input value:' + this.$('.source').val());
    this.model.set({
      "startPlace": this.$('.source').val()
    });
    console.log('startPlace set to: ' + this.model.get('startPlace'));
  },
  modelEvents: {
    "change:startPlace": "startMarkerDisplay",
    "change:endPlace": "endingMarkerDisplay"
  },
  startMarkerDisplay: function () {
    alert("start");
  },
  endingMarkerDisplay: function () {
    alert("end");
  }
});

$(document).ready(function(){
  var mapModelObj = new mapModel();
  var mapViewObj = new mapView({
    el: $('#mapDiv'),
    model: mapModelObj
  });
});

我建议的第二个解决方案

使用stickit库完成您所做的一切。您只需要定义dom选择器和观察到的模型属性之间的映射。

以下是jsfiddle:http://jsfiddle.net/orbanbotond/fm64P/

以下是代码:

var mapModel = Backbone.Model.extend({
  defaults: {
    startPlace: "initialStartPlace",
    endPlace: "initialEndplace"
  },
});

var mapView = Marionette.CompositeView.extend({
  template: "#mapDiv",
  events: {
    "blur .source": "sAttributeSetting",
    "blur .destination": "dAttributeSetting"
  },
  bindings: {
    '.source': {
      observe: 'startPlace'
    },
    '.destination': {
      observe: 'endPlace'
    }
  },
  onRender: function() {
    this.stickit();
    console.debug("Sticked to it already");
  },
});

$(document).ready(function(){
  var mapModelObj = new mapModel();
  var mapViewObj = new mapView({
    el: $('#mapDiv'),
    model: mapModelObj
  });
  mapViewObj.render();
    mapModelObj.bind('change:startPlace', function(obj){alert("New value: " + obj.get('startPlace'));});
    mapModelObj.bind('change:endPlace', function(){alert("New value: " + obj.get('endPlace'));});
});

对于我使用此模板的每个代码示例(我使用了类选择器而不是id选择器):

<div id="mapDiv">
    <input type="text" class="source">
    <input type="text" class="destination">
</div>