-->

ractive js : direct dom insertion sort/order for n

2019-09-12 15:17发布

问题:

I have seen lots of examples of using array based functions in Ractive for sorting and ordering lists but I was wondering if the same facility could be easily effected for nested object lists:

Assuming something like this:

var ractive = new Ractive({      
      el: 'main-col',
      template: $(templates).html(),
      data: {ObjList: {{key1:{x:data,y:dataB,....},{key2:{x:data,y:dataB,....},..       } });

template: {{#each ObjList}} render a card view per each key object nest {{/#each}}

I would like to be able to:

  1. Direct the DOM node/view placement order (not the actual object list per se since it inherently doesn't have an order) as #each nested object key dataset is rendered and
  2. Direct the insertion point of new DOM nodes resulting from ractive auto magic #each templating for new object insertions, at a specific point in the rendered #each list.

For example:

{{#each ObjList}}
<div>key1 data view</div>
<div>key2 data view</div>
<--------Insert new key5 nest object rendering in DOM tree, here
<div>key3 data view</div>
<div>key4 data view</div>
{{/ each}}

I currently have an array of just the key names, that track my desired sort order: sortArray=[key1,key2,key5,key3,key4...]. I use it as a linked list to traverse nested objects in a specific order for some progressive calculations. But 95% of my code and algorithms align with a keyed nested object list, as opposed to an array of objects.

I have considered three possibilities:

  1. some equivalent array sort like feature that could be easily effected at or post template rendering
  2. creating component instances for each individual nested list object and using the ractive DOM methods or
  3. brute forcing the virtual or real DOM, but I wasn't sure if that would break data binding.

I am 3 days into ractive so I was hoping someone might have a solution that would be the most "ractive" way. Right now my entire view is in a single Ractive instance, and I would like to continue the simplicity of that and the "auto magic" features of new renderings upon inserting a new key object member. The solution also needs to preserve two-way binding.

回答1:

Why not use a computed property based on your object. Just ractive.get the object data (thus registering a dependency) and return the values sorted however you like. In your template you will iterate through this new computed property. Whenever a new key is inserted, computed property will be updated automatically and then your template/view will be also ractively rerendered



回答2:

Per my initial intuition, I ended up pursuing choice 2 from my list of possible solutions. I created a component definition for my card view. I then referenced the card component in my parent template,within the parent template #each section/iterator, passing in a key identifier(so I could correlate which component instance was associated with which nested object key in future calls). I also templated things so the same key identifier was assigned to the container div id for each card component instance.

With those relationships in place, I was able to catch the instance event for default rendering(onrender) that auto magic appends new nested data objects to the end of the card view list. I effectively over rode that placement with a subsequent new placement using the ractive.insert method, within the event processing. By passing the parent div id and the desired sibling card div id(anchor) insertion point to ractive.insert, I was able to re-render the new card in the desired order.

While that addresses my original question for the add card use case, it still creates a lingering issue for a second use case: deleting a card. The associated active component instance for a nulled("deleted") nest object key is not removed from the parent container active component list. Nor is it de referenced after explicitly calling teardown for the instance (although it is removed from the view), so its instance specific data functions are still called post "delete." I suspect there is some data binding or teardown cleanup issue going on. I am going to follow up on that use case separately, because of concerns of potential memory leaks and processing overhead for phantom card instances.

See link below for codepen example:

Codepen Link

This codepen demonstrates the default ordering and the sorted version by toggling sort button