From Vue to Svelte Syntax

I’m building a small app with Svelte,  my last 2 years I was coding with Vue, so I found small differences with Vue,  let me explain a bit how is going my journey writing a Svelte component.

The password-strength project was build using the default svelte template, it generates main.js and src/App. svelte files, I assume you as worked before with Vue and just want to know a bit different from Svelte, you can read the full code in each version.

The Svelte and Vue default templates contain the same files only with extension differences .vue and .svelte,

  • The main.js is the entry point.
  • The App is the principal component.
  • The PasswordForm is used to demonstrates how to bind data, render tags and conditional render.

1- The entry point.

Svelte main.js

The component  main.js is the entry point similar to Vue, Svelte requires an import of the App.svelte component and configures the DOM node where it will be load.

import App from ‘./App.svelte’;

const app = new App({
    target: document.body
});

export default app;

Vue main.js

Vue need import Vue and attach the App component instance into the render and also call the $mount method with the DOM node where it will be load, a little bit more code but too similar to Svelte.

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

2- App Component

App.svelte

The Svelte import the PasswordForm component and render it.

<script>
    import PasswordForm from './components/PasswordForm.svelte';
</script>
<div class="container">
    <div class="row">
        <h1 class="title">Password Strength with Svelte</h1>
        <PasswordForm/>
    </div>
</div>

<style lang="scss">
    .title {
        text-align: center;
    }
</style>

App.vue

Vue needs the template tag and import the component and also register it on the components area.

<template>
  <div id="app" class="container">
    <div class="row">
      <h1 class="title">Password Strength with Vue</h1>
      <PasswordForm/>
    </div>
  </div>
</template>

<script>
import PasswordForm from './components/PasswordForm.vue'
import "./global.scss"
export default {
  name: 'app',
  components: {
    PasswordForm
  }
}
</script>

If you look, the svelte syntax is a bit shorter than Vue, but in terms of registration of components but not a big difference.

3- Working with data, render values and conditional render.

Vue provides the v-model for two way binding, double {{}} as render values, the computed functions for handle get the value when a prop used in the function change get a specific value and v-if directive for conditional render.

The component can be load using import in the components area to make our code a bit short.

PassForm.vue

<template>
  <div>
    <div class="row">
      <i>{{ notify }}</i>
      <div class="twelve columns">
        <label for="name">User</label>
        <input type="text" class="u-full-width" id="name" v-model="passModel.user"/>
      </div>
      <div class="twelve columns">
        <label>Password </label>
        <input class="u-full-width" type="password" v-model="passModel.password"/>
      </div>
      <div class="twelve columns">
        <PasswordPower v-if="passModel.password.length > 0" :pass-model="passModel"/>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "PasswordForm",
  data: () => ({
    passModel: {
      user: "",
      password: ""
    }
  }),
  components: {
    PasswordPower: () => import("./PasswordPower")
  },
  computed: {
    notify() { 
      return this.passModel.user.length > 2 ? "Hey " + this.passModel.user + ", thanks for use SveltePassword" : "Hello!" 
    }
  }
};
</script>

PasswordForm.svelte

Svelte import the component using the “import” statement and we can define an object to be used in the component as data, using $: allow react to changes of any property used in the right of it, is like a watch in vue, the example set the value of “notify” when user.length is > 0 another example is passModel.valid is set when password or user has values.

<script>
  import PasswordStrength from "./PasswordStrength.svelte";

  const passModel = {
    user: "",
    password: "",
    valid: false
  };

  $: notify =
    passModel.user.length > 0
      ? "Hey " + passModel.user + ", thanks for use SveltePassword"
      : "Hey Anonymous!";

  $: passModel.valid =
    passModel.password.length > 0 && passModel.user.length > 0;
</script>

<i>{notify}</i>
<div class="twelve columns">
  <label for="name">User</label>
  <input
    type="text"
    class="u-full-width"
    id="name"
    bind:value={passModel.user} />
</div>
<div class="twelve columns">
  <label for="password">Password</label>
  <input
    class="u-full-width"
    id="password"
    type="password"
    bind:value={passModel.password} />
</div>
<div class="twelve columns">
  {#if passModel.valid}
    <PasswordStrength {passModel} />
  {:else}
     <p>waiting for u</p>
  {/if}
</div>

#if is a conditional render and can be used to wrap some block with HTML or components and use :else for extra conditions.

{#if passModel.valid}
   <PasswordStrength {passModel} />
{:else }
   <p>Dammmm</p>
{/if}

Again the svelte syntax is a bit short, expect the #if, the v-if vue directive looks clean.

This was my first overview of svelte from the Vue perspective, the syntax is not complex but keeps in mind the following points.

  • I don’t have a default structure for components definitions.
  • The :$ looks weird at begin.
  • The #if..  and {: else} looks a bit ugly.

Hopefully, that will give you a bit of a head-start with Svelte, If you enjoyed this post, share it.

Thanks for reading!