0xedB0...3484

Turn your stories into NFTs

0 Following     0 Follower

Svelte versus Vue: a component case study

As I was writing in Transitioning from Vue to Svelte?, I've discovered the Svelte / SvelteKit combo about two weeks ago.

My Web3 publishing platform

I have been rewriting a full Web3 application since then which is taking me about two weeks, because this is a not so simple app: StoryPress.info is a Web3 application, that interacts with a good bunch of smart contracts. It has a state of the art online wysiwyg editor (on which I am currently writing this article), and all data written via this publishing platform is hosted on IPFS. It also has some clever tokenomics which you can monitor and interact with on the Cherry Merry dedicated pages.

Confession from a Vue fanatic

I have been a Vue/Nuxt fan for years, but I must tell that after almost two weeks of migrating from Nuxt to SvelteKit, I don't think I'll ever go back.

There are quite a few articles on the web comparing Svelte and Vue. They dive into many topics like comparing installation, community, app loading time, etc...

Here, I'll just focus on one thing, which is the heart of these Angular, React, Vue, Svelte frameworks: components.

And instead of writing long paragraphs, I'll just show you one of my components, explain what it does, and copy the Vue code as I was using it two weeks ago, and the Svelte code as it is now.

Then I'll just let you decide for yourself what looks better to your taste.

My tag component

Here is the case study: my tag editing component. You can see a screenshot of it just below:

And you can play with it on the story editor. It does the following:

  1. you can add a tag in an input field
  2. as soon as you type a coma, the input field splits in two and you can add a new tag
  3. each tag has a little X you can use to remove it
  4. I only allow 10 tags on StoryPress.info, so the number of tags left automatically updates
  5. I make sure the "s" at the end of "tags" disappear when there is just one tag left
  6. it makes the tags the user entered available to the rest of the application via a tags prop

Ok, it's not that complicated, but it's still quite a few lines of code.

Vue version

Here is the Vue version of the component:

// /components/TagsEditor.vue

<template>
  <form v-on:submit.prevent="addTag">
    <ul class="tags">
      <li v-for="(tag, index) in tags" :key="'tag-' + index">
        {{tag}}
        <span @click="tags.splice(index, 1)">X</span>
      </li>
      <li v-if="tags.length < 10"><input v-model="newTag" id="new-tag" @keyup="typing()" @blur="blurTag" :size="size" /></li>
      <li class="last-tag">{{ 10 - tags.length }} tag{{plural}} left</li>
    </ul>
  </form>
</template>


<script>
export default {
  props: ['tags'],


  data() {
    return {
      newTag: '',
    }
  },


  computed: {
    size: function() { return 3 + this.newTag?.length },
    plural: function() { return this.tags.length < 9 ? 's': '' },
  },


  methods: {

    typing: function() {
      if (this.newTag.indexOf(',') !== -1) {
        const bits = this.newTag.split(',')
        this.tags.push(bits[0])
        this.newTag = bits[1]
      }
    },

    addTag: function() {
      this.tags.push(this.newTag)
      this.newTag = ''
    },

    blurTag: function() {
      if (this.newTag) {
        this.addTag()
      }
    }
  }
}
</script>

Svelte version

// /src/lib/TagsEditor.svelte

<script>

export let tags = ['']

let newTag = ''

$: size = 3 + newTag?.length
$: plural = tags.length < 9 ? 's': ''

function typing() {
  if (newTag.indexOf(',') !== -1) {
    const bits = newTag.split(',')
    tags.push(bits[0])
    tags = tags
    newTag = bits[1]
  }
}

function addTag() {
  tags.push(newTag)
  tags = tags
  newTag = ''
}

function blurTag() {
  if (newTag) {
    addTag()
  }
}

function removeTag(idx) {
  tags.splice(idx, 1)
  tags = tags
}

</script>


<form on:submit|preventDefault={addTag}>
  <ul class="tags">
    {#each tags as tag, index}
      <li>
        {tag}
        <a href="#tags" on:click|preventDefault={() => removeTag(index)}>X</a>
      </li>
    {/each}
    {#if tags.length < 10}
      <li><input tabindex="0" bind:value={newTag} id="new-tag" on:keyup={typing} on:blur={blurTag} size={size} /></li>
    {/if}
    <li class="last-tag">{ 10 - tags.length } tag{plural} left</li>
  </ul>
</form>

What I like about Svelte

The best think I like about Svelte is that I just feel like I am writing JavaScript. I almost completely forget about the framework I am working in. No state to declare. If I want to declare a prop, I just put an export before my variable declaration.

In case I want to create a reactive variable, I just put a $: before it and that's it.

The rest is just vanilla javascript functions.

I don't need to nest my methods in computed: or methods: sub-objects. I don't need to define my state with data() return { mysState } ...

As you can see, I never go belong two levels of indentation with Svelte.

Now, you might prefer to write v-if="" inside a tag, instead of the probably more cumbersome {#if } {/if} that Svelte needs. But personaly, I find it makes the logic stand out, and HTML tags stay less messy.

If you have another opinion, please, share it in the comments. And if you liked this article, don't hesitate to drop me a like. ;-)

Reactions are currently disabled. They will return soon.

⏪ Previous Story

0xedB0...3484 avatar

Using Sequelize with SvelteKit

As you might have read in my previous story, Transitioning from Vue to Svelte?, I'm currently testing the ...
by 0xedB0...3484

⏩ Next Story

0xedB0...3484 avatar

StoryPress: from Vue to Svelte

Just a little article to announce that the transition of StoryPress from Vue/Nuxt to Svelte/SvelteKit is ...
by 0xedB0...3484