2

我认为给定具有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;
});

我还尝试添加一个名为fooupdate in的属性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.

那也没有用。

4

2 回答 2

3

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

Mithril将自身挂接到您视图的事件侦听器中。

因此,在我对 Mithril 的非常有限的经验中,您应该使用m设置事件侦听器或使用m.startComputation / m.endComputationwhich 调用m.redraw具有额外的好处,即允许您的应用程序的不同部分仅重绘一次,尽管更新了一些内容。

于 2014-06-18T19:34:52.397 回答
2

Mithril 自动重新渲染

  • 在所有已触发的事件处理程序,例如 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 的自动重绘系统在内部调用。

于 2014-07-02T14:17:41.440 回答