Vue 3 Splitting

Part of southcoastweb's contribution to Free and Open Source Software (FOSS)

Vue3 Splitting is a lightweight, Vue-centric version of Stephen Shaw’s and Christopher Wallis’ excellent JavaScript library Splitting. While Vue components are primarily data-driven, Splitting operated by manipulating the DOM directly. While there were alternatives (the html() function), these came with their own shortcomings in terms of support for Server-Side Rendering.

We also needed a few extra options when building the southcoast web site, namely the ability to independently control the enabling of char, word and line splitting and to offset the counts (allowing us to create multiple split blocks of text with consecutive counts). Since there didn’t seem to be an obvious Vue3 answer, we made one ourselves.

Installation

For those of you using NPM, you can install Vue3 Splitting like so:

npm i vue3-splitting

Or for the Yarn inclined:

yarn add vue3-splitting

While Vue3 Splitting itself doesn’t require installation, you can import the optional stylesheet which makes it easier to animate characters. Inside your Vue3 app:

import 'vue3-splitting/styles';

There are two ways of using Vue3 Splitting, the first is via a functional component which is geared towards those using the Composition API, the second is a standard Vue component which is for those using the Options API. We would recommend the former where possible.

FunctionalComponent

<script setup>
import { useSplitting } from "vue3-splitting";

const { Splitting, counts } = useSplitting('Hello World!', {
    // ... config goes here
});
</script>

useSplitting is composable which returns a functional component (Splitting) and a reactive counts object. The counts object is a Vue reactive which looks like this:

/*
counts = {
    chars: 27,
    words: 4,
    lines: 1
}
*/

At the moment, using the functional component is the only way to get the counts data.

Then, using the functional component in your template is as simple as:

<template>
    <Splitting />
</template>

You can pass HTML attributes to the functional component which will fall through to the rendered HTML element, but config settings for the output itself should be passed as the second argument to your composable function. Here’s what you can pass:

ConfigSettings

Name Type Description Default
lines boolean Split text by lines (
or \n)
true
words boolean Split text by words (whitespace) true
chars boolean Split text by characters true
lineOffset number Start counting lines at x 0
wordOffset number Start counting words at x 0
charOffset number Start counting characters at x 0
wrapperTag keyof HTMLElementTagNameMap Render the wrapping HTML element as x div
lineTag keyof HTMLElementTagNameMap Render each line HTML element as x div
lineClass string Add this class string to every line element
wordTag keyof HTMLElementTagNameMap Render each word HTML element as x span
wordClass string Add this class string to every word element
charTag keyof HTMLElementTagNameMap Render each character HTML element as x span
charClass string Add this class string to every character element

Note that the configuration object passed as the second argument to useSplitting can be either a standard JavaScript object, or a Vue reactive object (ref, reactive, computed etc.). If you pass the latter, the output of the functional component will automatically update.

FunctionalExample

In our example, we’re going to use a ref for our string input and a standard JavaScript object for our configuration. We’ve also performed a rename on the functional component from Splitting to MySplittingElement. You’ll need to do this if you want to use more than one Splitting functional components in the same Vue component.

const splittingString = ref('Hello World');
const { Splitting: MySplittingElement } = useSplitting(splittingString, {
    lineClass: 'my-splitting-element--line',
    words: false,
    wrapperTag: "h3"
});

StandardComponent

For those of you using the Options API, or who prefer to keep everything in the template, the standard component is a good alternative.

<script>
import { Vue3Splitting } from 'vue3-splitting';

export default {
    components: {
        Vue3Splitting
    }
};
</script>

<template>
    <Vue3Splitting class="my-4" wrapper-tag="ul" line-tag="li" :words="false">Hello World!</Vue3Splitting>
</template>

As you can see, on the standard component, the input string is passed through the default slot and both HTML attributes and config settings are passed as props on the component itself.

As with the input string for the composable, you’ll only be able to pass text, or a <br> tag inside the default slot of the Vue3Splitting component. Everything else will be ignored.

Feedback&Issues

If you come across any issues in Vue3 Splitting, or have any suggestions as to how we can make it better, please use the discussion or issues tab on the Github repository respectively.