如何创建自定义绑定以在每次*例程创建/销毁视图时获取回调?

时间:2014-10-10 03:00:39

标签: data-binding 2-way-object-databinding rivets.js

RivetJS太棒了!谢谢你让它不可知!

这是我flow所需的一项重要功能,而我正在努力使用RivetJS完成任务。

到目前为止,我能做的最多的事情是使用以下内容克隆以后的元素:

var theEachBind = rivets.binders['each-*'].bind;

      rivets.binders['each-*'].bind = function(el){
        console.info(this);
        theEachBind.call(this,el);
      };

而不是那里的console.info,我可以操纵Binder,但我认为这并不能帮助我完成这项工作。或者我可能会遗漏一些东西?

目前获得回调的计划是什么[each- *]创建和销毁视图?

对我来说,回调是理想的,所以我可以让控制器干净地维护它的子视图和子控制器。这需要Rivets.js中的功能请求吗?

2 个答案:

答案 0 :(得分:0)

已经请求了关于绑定的回调,但目前不在那里 https://github.com/mikeric/rivets/issues/337#issuecomment-59629266

答案 1 :(得分:0)

目前RivetJS中没有此功能。但是有关于制作它的讨论,希望我们能够实现目标。

为了今天完成这项工作,我所做的是使用铆钉的修改版本。我改变的是each-*活页夹上的例程。

我想要两个回调,一个是关于创建的,另一个是关于视图的破坏。我还需要为每个特定视图提供模型实例。

以下是我正在使用的each-*的完整例程。我的两行代码注释了一个像// sas:

这样的标签

你可以使用我在这里分享的routine版本以及这样的自定义绑定器来使用这些回调:

rivets.binders['iterated-*'] = rivets.binders['each-*];
var theEachBind = rivets.binders['each-*'].bind;
var theEachRoutine = rivets.binders['each-*'].routine;

rivets.binders['iterated-*'].bind = function(el){
    this.view.onViewCreated = function(aView, aModel){ self._onViewCreated_for_(aView, aModel) };
    this.view.onViewDestroyed = function(aView, aModel){ self._onViewDestroyed_for_(aView, aModel)};
    theEachBind.call(this,el);
};

作为奖励,这是每次例行评估时获得回调的方式:

rivets.binders['iterated-*'].routine = function(el, collection){
    var results = theEachRoutine.call(this, el, collection);
    self._onRoutine_value_(el, collection);
    return results;

有了这个,你会被召唤回来:

  1. _onViewCreated_for_(aView, aModel)
  2. _onViewDestroyed_for_(aView, aModel)
  3. _onRoutine_value_(el, collection)
  4. 这就是我在flow的IteratedControllers中使用它的方法,它们维护任意复杂的子项的创建和破坏。

    最后,这里有自定义rivetjs代码:

    routine: function(el, collection) {
      var binding, data, i, index, k, key, model, modelName, options, previous, template, v, view, _i, _j, _k, _len, _len1, _len2, _ref1, _ref2, _ref3, _ref4, _results;
      modelName = this.args[0];
      collection = collection || [];
      if (this.iterated.length > collection.length) {
        _ref1 = Array(this.iterated.length - collection.length);
        for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
          i = _ref1[_i];
          view = this.iterated.pop();
          view.unbind();
    
          // sas: this one is for the view destroy callback
          if(this.view.onViewDestroyed){this.view.onViewDestroyed(view, view.models[modelName])};
    
          this.marker.parentNode.removeChild(view.els[0]);
        }
      }
      for (index = _j = 0, _len1 = collection.length; _j < _len1; index = ++_j) {
        model = collection[index];
        data = {
          index: index
        };
        data[modelName] = model;
        if (this.iterated[index] == null) {
          _ref2 = this.view.models;
          for (key in _ref2) {
            model = _ref2[key];
            if (data[key] == null) {
              data[key] = model;
            }
          }
          previous = this.iterated.length ? this.iterated[this.iterated.length - 1].els[0] : this.marker;
          options = {
            binders: this.view.options.binders,
            formatters: this.view.options.formatters,
            adapters: this.view.options.adapters,
            config: {}
          };
          _ref3 = this.view.options.config;
          for (k in _ref3) {
            v = _ref3[k];
            options.config[k] = v;
          }
          options.config.preloadData = true;
          template = el.cloneNode(true);
          view = new Rivets.View(template, data, options);
          view.bind();
    
          // sas: this is for the create callback
          if(this.view.onViewCreated){this.view.onViewCreated(view, data[modelName])};
    
          this.iterated.push(view);
          this.marker.parentNode.insertBefore(template, previous.nextSibling);
        } else if (this.iterated[index].models[modelName] !== model) {
          this.iterated[index].update(data);
        }
      }
      if (el.nodeName === 'OPTION') {
        _ref4 = this.view.bindings;
        _results = [];
        for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {
          binding = _ref4[_k];
          if (binding.el === this.marker.parentNode && binding.type === 'value') {
            _results.push(binding.sync());
          } else {
            _results.push(void 0);
          }
        }
        return _results;
      }
    },
    

    PS:让我高兴的是能够弃用iterated-*并将这些回调视为each-*的常规功能