Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't destroy/recreate views on each reposition #1

Open
tarqd opened this issue May 6, 2014 · 5 comments
Open

Don't destroy/recreate views on each reposition #1

tarqd opened this issue May 6, 2014 · 5 comments

Comments

@tarqd
Copy link

tarqd commented May 6, 2014

Using a Least-Common-Sequence algorithm such as that employed by benjamine/jsondiffpatch or Polymer/observe-js you can avoid having to recreate the elements on each reposition. You'd just need to apply the appropriate splices (or adds/removes) and only need to recreate views for newly added elements.

I've seperated the array diff/patch algorithms from jsondiffpatch in this library. (doesn't work with current versions of reactive though) which may be useful.

@anthonyshort
Copy link
Contributor

This is awesome. I'd love to get this in there so it doesn't re-render everything every time. I'll definitely look at adding this in. The each plugin will probably just stay simple for basic use-cases, but I'm writing another plugin for more complex lists that will use this algorithm. I'd love to get some help on it if this is something you're more familiar with.

@tarqd
Copy link
Author

tarqd commented May 28, 2014

I'd love to offer help with the new plugin! Unless you've already done so I'd definitely want to do a rewrite as the code is currently really ugly and hard to follow (it's mostly directly lifted from jsondiffpatch which is an awesome library but isn't very easy on the eyes haha). There are some gotcha's with this kind of method though, for example the lists must contain unique elements.

Off the top of my head the easiest way to do comparisons with either use valueOf or something like toHashCode which can be implemented by user objects. This is probably the least intrusive way to go about it. In my example I just store the "hashes" of objects in an array with their associated views and compare them to the hashes of the mutated set

@anthonyshort
Copy link
Contributor

Sounds great. I'd love to get help on this. Iteration is the hardest part about building views. If we can get this plugin nailed correctly it will mean building views will be really easy and much more lightweight than things like React or Angular.

I've started playing with the type of API I want for it but I haven't really written any code yet. Hopefully this could be its own module and not tied too tightly to the list plugin. Could we just provide a unique ID on each of the views and use that for comparison? Or would we want the built hash code to be determined by the content?

@tarqd
Copy link
Author

tarqd commented May 29, 2014

I think we'd want the hash code to be determined by content. This way users can directly manipulate the arrays in anyway they see fit (moving models around etc) and the algorithm will pick up the changes. By default it could use object equality (this is default behavior in angular as well) but would allow something like

<li each="comments by _id">{{text}}</li>

Although now that I've typed it out it seems like just doing object equality would be fine, since if you're moving a comment you'd presumably be using the same comment object. Unless you're refreshing the whole array from the server, but in that case you could argue the correct behavior would be to refresh all the views as well. Angular just adds that list by key magic to make it so replacing the whole array will work as if you did the merging of changes yourself. This might be a little too magicy for ripplejs though, seems easy to become a source of bugs

@tarqd
Copy link
Author

tarqd commented May 29, 2014

With object equality you'd either have to keep a copy of each object in the list so you have a reference to compare to (potentially leaky) or store the generated hash/id on the object and just keep an array of the ids. That's the method that angular goes with ($$hashKey). If you decide to go that route it might be a good idea to use something like weakmap or any of the other weakmap/private name polyfills. With the added bonus that eventually you can remove them when browsers add support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants