当模型更新时,backbone和knockout如何使视图发生变化?

发布于 2024-12-25 03:45:37 字数 164 浏览 0 评论 0原文

我正在深入研究这两个很棒的作品的源代码,但是,我无法弄清楚它们的实现,模型数据更新视图的那一刻如何立即改变,
一开始,我认为它可能在 Gecko 中使用类似 object.watch() 的东西,显然我在两个来源中都找不到它们
他们的核心思想有什么想法
先谢谢啦~

I'm diving into the source code of these two awesome works,however,I can't figure out the implement of them,how can the moment the data of the model update the view immedately changes,
At the very first beginning,I thought it may use something like object.watch() in Gecko,and obviously I can't find them in both sources
any ideas of the core thought of them
Thanks in advance~

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橘虞初梦 2025-01-01 03:45:37

让我们看一下backbone 事件实现:

调用bind 将传递的函数(回调)存储在散列_callbacks 中的传递键(ev) 下。

Backbone.Events = {

    // Bind an event, specified by a string name, `ev`, to a `callback` function.
    // Passing `"all"` will bind the callback to all events fired.
    bind : function(ev, callback, context) {

      //create a new hash to save the callbacks when it doesn't exits yet
      var calls = this._callbacks || (this._callbacks = {});

      //create a new array to store the callbacks if its doesn't exits yet
      var list  = calls[ev] || (calls[ev] = []);

      //add a new array holding the function and the context with which the function 
      // will be called later
      list.push([callback, context]);

      return this;
    },

解除绑定只是从哈希中删除所有或传递的回调。

    // Remove one or many callbacks. If `callback` is null, removes all
    // callbacks for the event. If `ev` is null, removes all bound callbacks
    // for all events.
    unbind : function(ev, callback) {
      var calls;
      if (!ev) {
        this._callbacks = {};
      } else if (calls = this._callbacks) {
        if (!callback) {
          calls[ev] = [];
        } else {
          var list = calls[ev];
          if (!list) return this;
          for (var i = 0, l = list.length; i < l; i++) {
            if (list[i] && callback === list[i][0]) {
              list[i] = null;
              break;
            }
          }
        }
      }
      return this;
    },

触发器将调用存储在传递的密钥下的所有函数。

    // Trigger an event, firing all bound callbacks. Callbacks are passed the
    // same arguments as `trigger` is, apart from the event name.
    // Listening for `"all"` passes the true event name as the first argument.
    trigger : function(eventName) {
      var list, calls, ev, callback, args;
      var both = 2;
      if (!(calls = this._callbacks)) return this;
      while (both--) {
        ev = both ? eventName : 'all';
        if (list = calls[ev]) {
          for (var i = 0, l = list.length; i < l; i++) {
            if (!(callback = list[i])) {
              list.splice(i, 1); i--; l--;
            } else {
              //when more then one argument was passed to the trigger function
              // this arguments will be passed to call of the stored function
              args = both ? Array.prototype.slice.call(arguments, 1) : arguments;

              //here the stored function is called with the optional passed context
              callback[0].apply(callback[1] || this, args);
            }
          }
        }
      }
      return this;
    }

  };

这是 JavaScript 的优点之一,您可以将函数及其完整范围存储在变量中并稍后调用它们。所以添加结束数据绑定没有魔法。它只是一个数据结构,用于将带有键的函数保存在哈希中并使用该键调用它们。

由于 Backbone 对象 View、Model、Controller 扩展了 Events 对象,因此您可以在所有对象上绑定/触发事件。因此,当视图在模型更改上绑定函数时,模型会在添加、删除等内容时调用 this.trigger('change')

Lets take a look at backbones Event implementation:

Calling bind you store a passed function (callback) under passed key (ev) in the hash _callbacks.

Backbone.Events = {

    // Bind an event, specified by a string name, `ev`, to a `callback` function.
    // Passing `"all"` will bind the callback to all events fired.
    bind : function(ev, callback, context) {

      //create a new hash to save the callbacks when it doesn't exits yet
      var calls = this._callbacks || (this._callbacks = {});

      //create a new array to store the callbacks if its doesn't exits yet
      var list  = calls[ev] || (calls[ev] = []);

      //add a new array holding the function and the context with which the function 
      // will be called later
      list.push([callback, context]);

      return this;
    },

Unbind just delete all or the passed callbacks from the hash.

    // Remove one or many callbacks. If `callback` is null, removes all
    // callbacks for the event. If `ev` is null, removes all bound callbacks
    // for all events.
    unbind : function(ev, callback) {
      var calls;
      if (!ev) {
        this._callbacks = {};
      } else if (calls = this._callbacks) {
        if (!callback) {
          calls[ev] = [];
        } else {
          var list = calls[ev];
          if (!list) return this;
          for (var i = 0, l = list.length; i < l; i++) {
            if (list[i] && callback === list[i][0]) {
              list[i] = null;
              break;
            }
          }
        }
      }
      return this;
    },

Trigger will call all functions that stored under the passed key.

    // Trigger an event, firing all bound callbacks. Callbacks are passed the
    // same arguments as `trigger` is, apart from the event name.
    // Listening for `"all"` passes the true event name as the first argument.
    trigger : function(eventName) {
      var list, calls, ev, callback, args;
      var both = 2;
      if (!(calls = this._callbacks)) return this;
      while (both--) {
        ev = both ? eventName : 'all';
        if (list = calls[ev]) {
          for (var i = 0, l = list.length; i < l; i++) {
            if (!(callback = list[i])) {
              list.splice(i, 1); i--; l--;
            } else {
              //when more then one argument was passed to the trigger function
              // this arguments will be passed to call of the stored function
              args = both ? Array.prototype.slice.call(arguments, 1) : arguments;

              //here the stored function is called with the optional passed context
              callback[0].apply(callback[1] || this, args);
            }
          }
        }
      }
      return this;
    }

  };

This is one of the advantages of JavaScript that you can store functions with its full scope in a variable an call them later. So add the end there is no magic in databinding. Its just a data structure to save function with an key in a hash and call them using the key.

As the Backbone object View, Model, Controller extends the Events object, you can bind/trigger events on all of it. So when a view binds a function on model change, the model call this.trigger('change') on when ever something was added, removed etc.

2025-01-01 03:45:37

我不熟悉 Knockout,但 Backbone 在数据更改时手动触发事件。来自 Model#set

if (!alreadyChanging && !options.silent && this._changed) this.change(options);

这是来自 Model#change

change : function(options) {
  this.trigger('change', this, options);
  this._previousAttributes = _.clone(this.attributes);
  this._changed = false;
},

视图可以监听 change 事件并相应更新。

I'm not familiar with Knockout, but Backbone fires an event manually when data is changed. From Model#set:

if (!alreadyChanging && !options.silent && this._changed) this.change(options);

and this is from Model#change:

change : function(options) {
  this.trigger('change', this, options);
  this._previousAttributes = _.clone(this.attributes);
  this._changed = false;
},

Views can listen to the change event and update accordingly.

长梦不多时 2025-01-01 03:45:37

Backbone.JS

你的视图需要监听它的模型,并触发模型的更改事件。

this.model.bind('change', this.render, this);

我为您创建了一个 jsFiddle 来看看它是如何工作的: http://jsfiddle.net/Atinux/Jb2rd/

我不太了解 Knockout JS,但我不认为这是一样的,如果我找到答案,我会更新我的帖子。

Backbone.JS

Your view need to listen its model, and trigger the model's change event.

this.model.bind('change', this.render, this);

I created for you a jsFiddle to see how It works : http://jsfiddle.net/Atinux/Jb2rd/

I don't really know Knockout JS but I don't think that's the same way, I'll update my post if I find the answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文