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

Data binding 如何创建自定义绑定以在每次-*例程创建/销毁视图时获得回调?,data-binding,2-way-object-databinding,rivets.js,Data Binding,2 Way Object Databinding,Rivets.js,太棒了!谢谢你让它成为不可知论者 这是我需要的一个关键特性,我正在努力使用它来完成它 到目前为止,我所能做的最多的事情就是获取稍后将要使用以下内容克隆的元素: var theEachBind = rivets.binders['each-*'].bind; rivets.binders['each-*'].bind = function(el){ console.info(this); theEachBind.call(this,el);

太棒了!谢谢你让它成为不可知论者

这是我需要的一个关键特性,我正在努力使用它来完成它

到目前为止,我所能做的最多的事情就是获取稍后将要使用以下内容克隆的元素:

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

      rivets.binders['each-*'].bind = function(el){
        console.info(this);
        theEachBind.call(this,el);
      };
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);
};
我可以操作活页夹,而不是那里的
console.info
,但我认为这并不能真正帮助我完成这项工作。或者我可能错过了什么

在[each-*]创建和销毁视图的那一刻,获得回调的计划是什么


对我来说,回调将是理想的,这样我可以使控制器干净地维护其子视图和子面板。这是否需要铆钉.js中的功能请求?

已请求绑定回调,但目前不在其中

目前,该功能在FirefoxJS中不存在。但我们正在讨论如何做到这一点,希望我们能做到

为了今天完成这项工作,我使用了一种改进版的铆钉。我改变的是
每个-*
活页夹上的例程

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

下面是我正在使用的
每个-*
的完整例程。我的两行代码都用这样的标签注释
//sas:

您可以使用我在这里共享的
routine
版本以及如下自定义活页夹来使用这些回调:

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

      rivets.binders['each-*'].bind = function(el){
        console.info(this);
        theEachBind.call(this,el);
      };
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;
有了这些,您将被召回:

  • \u onViewCreated\u for(aView,aModel)
  • \u onviewdestromed\u for(aView,aModel)
  • \u on例程\u值(el,集合)
  • 这就是我在IteratedController中使用它的方式,它们维护任意复杂子对象的创建和销毁

    最后,这里是使这成为可能的自定义代码:

    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;
      }
    },
    
    例程:功能(el、采集){
    变量绑定、数据、i、索引、k、键、模型、模型名、选项、上一个、模板、v、视图、i、j、k、len、len1、len2、ref1、ref2、ref3、ref4、结果;
    modelName=this.args[0];
    集合=集合| |[];
    if(this.iterated.length>collection.length){
    _ref1=数组(this.iterated.length-collection.length);
    对于(_i=0,_len=_ref1.length;_i<_len;_i++){
    i=_ref1[_i];
    view=this.iterated.pop();
    view.unbind();
    //sas:这一个用于查看销毁回调
    if(this.view.onViewDestroyed){this.view.onViewDestroyed(view,view.models[modelName]);
    this.marker.parentNode.removeChild(view.els[0]);
    }
    }
    对于(索引=_j=0,_len1=collection.length;_j<_len1;索引=++_j){
    模型=集合[索引];
    数据={
    索引:索引
    };
    数据[modelName]=模型;
    if(this.iterated[index]==null){
    _ref2=this.view.models;
    用于(输入参考2){
    模型=_ref2[键];
    如果(数据[键]==null){
    数据[键]=模型;
    }
    }
    previous=this.iterated.length?this.iterated[this.iterated.length-1].els[0]:this.marker;
    选项={
    活页夹:this.view.options.binders,
    格式化程序:this.view.options.formatters,
    适配器:this.view.options.adapters,
    配置:{}
    };
    _ref3=this.view.options.config;
    用于(k英寸参考文献3){
    v=_ref3[k];
    options.config[k]=v;
    }
    options.config.preload数据=true;
    模板=el.cloneNode(真);
    视图=新铆钉。视图(模板、数据、选项);
    view.bind();
    //sas:这是用于创建回调的
    if(this.view.onViewCreated){this.view.onViewCreated(view,data[modelName]);
    this.iterated.push(视图);
    this.marker.parentNode.insertBefore(模板,previous.nextSibling);
    }else if(this.iterated[index].models[modelName]!==model){
    此.iterated[index].更新(数据);
    }
    }
    如果(el.nodeName==='OPTION'){
    _ref4=this.view.bindings;
    _结果=[];
    对于(_k=0,_len2=_ref4.length;_k<_len2;_k++){
    绑定=_ref4[_k];
    if(binding.el==this.marker.parentNode&&binding.type===value'){
    _results.push(binding.sync());
    }否则{
    _结果:推挤(无效0);
    }
    }
    返回结果;
    }
    },
    

    PS:让我高兴的是,能够不推荐
    iterated-*
    ,并将这些回调视为
    每个-*

    的常规功能,谢谢@Symeon,这也很方便。