为什么m.module不会让我的观点在秘银中重新投降?

时间:2014-06-16 21:08:21

标签: javascript mithril.js

我认为给定controller& view属性,当控制器的状态发生变化(或m.prop属性发生变化)时,它会重新呈现模板。在我的情况下,这不会发生(我必须直接使用redraw)。我在这做错了什么?     //////// app.js

define([ 'mithril', 'propertyPane'],
  function(m, propertyPane){
    //div#properties exists
    m.module(document.getElementById('properties'),propertyPane);
});

///////propertyPane.js

define([ 'mithril', 'emitter'],
  function(m, emitter) {

    //mithril "namespace"
    var propertyPane = {};

    ///////////////////////
    //    Models         //
    ///////////////////////
    propertyPane.PropertyList = Array;

    propertyPane.Property = function(name, data) {
      //the following reflects the format of the data obects as sent by the event emitter
      this.name        = m.prop(name);
      this.value       = m.prop(data.value);
      this.type        = m.prop(data.valueType);
      this.visible     = m.prop(data.userVisible);
      this.editable    = m.prop(data.userEditable);
    };

    ///////////////////////
    //    Controller     //
    ///////////////////////
    propertyPane.controller = function() {

      this.properties = propertyPane.PropertyList();

      this.updatePropertyPane = function(sender) {
        //destroy current list
        this.properties.length = 0;

        for( var key in sender.currentItem.tag){
          this.properties.push(new propertyPane.Property(key, sender.currentItem.tag[key]));
        }
//>>>This is required to make the property pane to rerender:<<<
//      m.redraw(); //why?
//why doesn't redraw happen automatically (because I'm using m.module)??
      }.bind(this);

      //this reliably updates the the properties list
      //but rerender does not happen
      emitter.addCurrentItemChangedListener(this.updatePropertyPane);

    };

    ///////////////////////
    //    View           //
    ///////////////////////
    propertyPane.view = function(ctrl){
      return m('ul',
        ctrl.properties.map(function(property){
          return m('li', property.name() + ' ' + property.value());
        })
      );
    };

    return propertyPane;
});

我还尝试添加一个名为foo的属性,该属性在updatePropertyPane中更新了:

//in controller
this.foo = m.prop(Date.now());
//in updatePropertyPane
  this.foo(Date.now());
//in view
m('li', ...+this.foo()) //to make sure the view accesses this property.

那也不起作用。

2 个答案:

答案 0 :(得分:3)

令人惊讶的是,m.prop非常多地返回一个getter / setter而没有副作用。

Mithril hooks本身就是你观点的事件听众。

因此,在我使用秘银的经验非常有限的情况下,您应该使用m来设置您的事件监听器,或者使用m.startComputation / m.endComputation来调用m.redraw,并允许您使用{{1}}的不同部分。应用到only redraw once尽管更新了几件事。

答案 1 :(得分:2)

秘银自动重新渲染

  • 在所有事件处理程序之后,例如m(tag,{onclick:...},foo)已被终止。
  • AJAX请求已终止。
  • 路由发生。

数据绑定值更改本身不会导致重新呈现,这有几个原因。公平地说,Mithril中的大多数数据更改都发生在事件处理程序中或AJAX处理期间。

但是,您可以使用m.prop()的修改版本强制重新更改值:

mprop: function(store, onchange) {
    var prop = function() {
        if (arguments.length) {
            store = arguments[0];
            if (typeof onchange == 'function') { onchange(store); }
        }
        return store;
    }
    prop.toJSON = function() { return store; }
    return prop;
}

this.name = mprop("John", function(value) {
    // value is the new value
    // do a m.redraw() rather than m.startComputation / m.endComputation
});

但是你这样做,你应该更喜欢m.redraw()用于m.startComputation / m.endComputation上的异步事件。它重绘了当前活动模块的视图,并由Mithril的自动重绘系统在内部调用。