npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-recursion

v0.0.4

Published

a renderless vue component that handles recursion logic

Downloads

17

Readme

Vue-Recursion

This is a renderless component that handles the recursion logic and expects the render template as its children. This Component expects the tree data as a prop, then uses it to render nodes recusibly. At each node, the tree item data and other node information are obtained through the exposed v-slot prop of the component. This will be better explained in the examples.

Installation

npm install vue-recursion

Use

To use the component (once it's already installed) you just need to import it.

<script lang="ts" setup>
import Recursion from 'vue-recursion';
import { reactive } from 'vue';
//...
const nested_list_data = reactive<t_node<number>>([0,[
  [1,[
  [5],
  [6]
  ]],
  [2],
  [3,[
  [7],
  [8]
  ]],
  [4],
]]);
</script>

You can also import the helper types this way

<script lang="ts" setup>
import { default as Recursion, type t_node } from 'vue-recursion';
import { reactive } from 'vue';
//...

//It's not required to make the data reactive if you want to render the data statically
const nested_list_data = reactive<t_node<number>>([0,[
  [1,[
  [5],
  [6]
  ]],
  [2],
  [3,[
  [7],
  [8]
  ]],
  [4],
]]);
</script>

Simple nested list example

The most basic recursion example in web are nested list. This is a way of displaying them using the Recursion Component.

<template>
  <ul class="list">
    <Recursion :data="nested_list_data" v-slot="{ component, data }">
      <li>
        <p>{{ data }}</p>
        <ul class="list">
          <component :is="component"/>
        </ul>
      </li>
    </Recursion>
  </ul>
</template>
<!--output-->
<ul>
	<li>0
    <ul>
			<li>1
        <ul>
					<li>5
            <ul></ul>
					</li>
					<li>6
            <ul></ul>
					</li>
				</ul>
			</li>
			<li>2
        <ul>
				</ul>
			</li>
			<li>3
        <ul>
					<li>7
            <ul></ul>
					</li>
					<li>8
            <ul></ul>
					</li>
				</ul>
			</li>
			<li>4
        <ul>
				</ul>
			</li>
		</ul>
	</li>
</ul>

As shown, the component receives the data as a tree structure and the rendering template as a child (<li>...</li>), then exposes the children recursive elements in the form of the component v-slot prop. This is very similar in the way that vue-router handles the styling of child pages, allowing the user to wrap the rendered page in a custom layout.

Custom recursion wrapper

In the previous example, the <component> renders the child elements of each iteration of the recursion as fragments. However, in order to allow more customization in the way a component is rendered, the <Recursion> component also exposes the components as an iterable array. This allows the component to have a root-node element that can later be used to be animated using the Transition Group built-in component.

<template>
  <ul class="list">
    <Recursion :data="nested_list_data" v-slot="{ components, data }">
      <li>
        <p>{{ data }}</p>
        <TransitionGroup name="list" tag="ul" class="list">
          <li v-for="c in components" :key="c.key"> 
            <component :is="c"/>
          </li>
        </TransitionGroup>
      </li>
    </Recursion>
  </ul>
</template>

Use with custom component

Of course, the Recursion component allows the use of custom components as children.

<script lang="ts" setup>
//Comp
const p = defineProps<{
  n : number;
  t : string;
}>();  

</script>

<template>
  <li>
    <p>value : {{ p.n }} - {{ p.t }}</p>
    <ul>
      <slot><li>no children</li></slot>
    </ul>
  </li>
</template>
<template>
  <ul>
    <Recursion :data="
      [{ 
        n : 0,
        t : 'zero'
        key : 0,
        },[
          [{
            n : 12,
            t : 'twelve',
            key : 1,
          }, [
            [{
              n : 4,
              t : 'four',
              key : 2,
            }],
            [{
              n : 5,
              t : 'five',
              key : 3,
            }],[{
              n : 8,
              t : 'eight',
              key : 4,
            }]
          ]],
          [{
            n : 3,
            t : 'tree',
            key : 5,
          }]
      ]]" v-slot="{ component, data }">

      <Comp :n="data.n" :t="data.t" :key="data.key">
        <component :is="component"/>
      </Comp>
    </Recursion>
  </ul>
</template>

Now, something very important here is the key property in the data objects when using non primitive values as items for the tree.

Guide

This component handles most logic internally but has one required prop which is the data. The data type is defined as

//The data tree node type is defined as a tuple
type t_node<T = unknown> = [T, t_node[]?];

where, the first element of the tuple is the tree node's item and the second is the array of children nodes.

The Recursion v-slot exposes more than only the data and the component & components objects.

type t_slotprops<T = any> = {
	data : T,
	depth : number,
	index : number,
	children : Readonly<raw_tree_branch<T>[]>,
	chain : number[],
		
	component? : unknown,
	components : unknown[],
};

| Property | Type | description | |---|---|---| | data | any | Represents the item of the current node. This property is defined by the used when the tree is passed as a prop to the component. | | depth | number | The depth of the recursion of the current node. The root node with get a value of 0. | | index | number | The index of this current node inside its parent children array. | | children | readonly t_node[] | (CAUTIOUS USE) the raw readonly array list of children of the current node. | | component | | The fragment component that renders the child recursion nodes. | | components | [] | An array of components. Each one renders a child recursion node. Each node also exposes its key. |

In order to better use the exposed properties, this Component exposes a type t_slotprops that can be used to strongly type the data property.

<template>
  <Recursion :data v-slot="{ data, component } : t_slotprops<number>">
    {{ data }} <!-- here data is now recognized as number -->
    <component :is="component"/>
  </Recursion>
</template>

When using non-primitive item types is optional but strongly recommended to add a key property to each node item, which should be a primitive unique value number | string | symbol.