Question

I am working on a Spine App that users rivets js in lieu of a templating engine and so far I am delighted with the rivets bindings, my views are more concise and readable and I have a clean separation of concerns: my controllers only take care of managing the state of the app, my models do the persistence stuff and my custom rivet bindings and formatters take care of formatting values and massaging user input. So far so good.

My only concern is that I am using watch.js and I suspect watch is responsable for iphone performance issues, and I not too comfortable using it.

In rivets js site it states that it has support for Spine although I haven't been able to find a single example let alone a snippet.

The only adapter that works both for controllers and models I could come up with is this:

rivets.configure adapter:
  subscribe: (obj, keypath, callback) ->
    watch obj, keypath, callback

  unsubscribe: (obj, keypath, callback) ->
    unwatch obj, keypath, callback

  read: (obj, keypath) ->
    obj[keypath]

  publish: (obj, keypath, value) ->
    obj[keypath] = value

Is there a better way to binding rivets to spine models and controllers?

I've been struggling with Object.defineProperty to no avail.

Était-ce utile?

La solution

Spine.js doesn't emit events when you change attributes on the model, it only fires an event when you call save() on the model. It also doesn't perform any sort of dirty tracking, so you don't get update:keypath style events out-of-the-box, it just fires a single update event.

Here's a standard adapter for using Spine.js models with Rivets.js.

rivets.configure
  adapter:
    subscribe: (obj, keypath, callback) ->
      obj.bind "update", callback

    unsubscribe: (obj, keypath, callback) ->
      obj.unbind "update", callback

    read: (obj, keypath) ->
      obj[keypath]

    publish: (obj, keypath, value) ->
      obj[keypath] = value

Using the above adapter, Rivets.js will update the in-memory attributes on your models when going from view-to-model (using a two-way binder such as value or checked) and will update the view (going from model-to-view) only when you call save() on the model. This is just part of how Spine.js events work.

Unfortunately the above adapter will update every binding for that model, including bindings for properties that did not change. Alternatively, you can use something like Spine-Attribute-Events which does basic dirty tracking and fires an additional update:keypath style event for the attributes that changed. This will be far more performant in terms of DOM operations as we're only updating what needs to be updated.

rivets.configure
  adapter:
    subscribe: (obj, keypath, callback) ->
      obj.bind "update:" + keypath, callback

    unsubscribe: (obj, keypath, callback) ->
      obj.unbind "update:" + keypath, callback

    read: (obj, keypath) ->
      obj[keypath]

    publish: (obj, keypath, value) ->
      obj[keypath] = value

As you can see, this gives Rivets.js a more granular way to subscribe to individual attribute changes. The basic idea here is that Rivets.js will now update only the parts of the DOM for attributes that have changed.

Again all of this happens only when you call save(), which is actually a nice feature because you can make as many intermediate changes to the model as you want, and then call save() at the very end to have those changes reflected in the UI.

Autres conseils

I am not the expert, but that seems to be a correct adapter configuration file for Watch.js.

But that may not be your performance problem. Try this link for more performance hints: How to bind deeper than one level with rivets.js

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top