Elm vs. Vue.js: Comparisons from a Front-End Developer

Elm vs. Vue.js: Comparisons from a Front-End Developer

I thought it would be interesting to quickly compare how to do a small bit of UI in Elm and Vue.js that are both used for the web. I’ll be doing this from a perspective of my role as a frontend developer working on web apps at carwow.

I thought it would be interesting to quickly compare how to do a small bit of UI in two completely different languages that are both used for the web, rather than the typical JS framework v JS framework battle that repeats and rages on, year on year. After that then looking at a few pros and cons of each.

I’ll be doing this from a perspective of my role as a frontend developer working on web apps at carwow.

What’s Elm and what’s Vue?

There’s a stark contrast between Vue and Elm. The first one being that one is a JavaScript framework and the other, Elm, is a functional language in its own right. Elm is eventually compiled to JavaScript as that is what the browser understands. Both Elm and Vue are used for creating UI on the web.

Maybe you’ve done some Elm or Vue before, but if not let’s look at a quick example of how we would achieve a simple bit of UI using both. We’ll not get bogged down in the initialisation of an app and how to add it to the page etc, instead we’ll just look at an Elm and Vue file as a single component.


Let’s show something extremely simple. We’ll create the markup for the below in Vue and Elm.

Elm and Vue.js

Now brace yourself for an Elm and Vue code dump…

module Main exposing (Model, init)

import Browser
import Html exposing (..)
import Html.Attributes exposing (..)

type alias Model =
    { vueTitleText : String
    , vueTitleDescription : String
    , elmTitleText : String
    , elmTitleDescription : String

type alias Flags =

init : Flags -> ( Model, Cmd msg )
init flags =
        model =
            { vueTitleText = "Vue"
            , vueTitleDescription = "JavaScript Framework"
            , elmTitleText = "Elm"
            , elmTitleDescription = "Functional Language"
    ( model, Cmd.none )

update : msg -> Model -> ( Model, Cmd msg )
update msg model =
    ( model, Cmd.none )

view : Model -> Html msg
view model =
    div [ class "container" ]
        [ div [ class "container__inner" ]
            [ div [ class "container__inner-content" ]
                [ h2 [ class "container__inner-content-title" ] [ text model.vueTitleText ]
                , p [ class "container__inner-content-description" ] [ text model.vueTitleDescription ]
        , div [ class "container__inner" ]
            [ div [ class "container__inner-content" ]
                [ h2 [ class "container__inner-content-title" ] [ text model.elmTitleText ]
                , p [ class "container__inner-content-description" ] [ text model.elmTitleDescription ]

subscriptions : Model -> Sub msg
subscriptions _ =

main : Program Flags Model msg
main =
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions

Creating the example above in Elm (minus the CSS)

  <div class="container">
    <div class="container__inner">
      <div class="container__inner-content">
        <h2 class="container__inner-content-title">this.vueTitleText</h2>
        <p class="container__inner-content-description">this.vueTitleDescription</p>
    <div class="container__inner">
      <div class="container__inner-content">
        <h2 class="container__inner-content-title">this.elmTitleText</h2>
        <p class="container__inner-content-description">this.elmTitleDescription</p>

  export default {
    data: {
      vueTitleText: "Vue",
      vueTitleDescription: "JavaScript Framework",
      elmTitleText: "Elm",
      elmTitleDescription: "Functional Language"

<style lang="scss" scoped>


Creating the example above in Vue (minus the CSS)


Writing HTML

In Vue, the markup looks like plain old HTML, although you can choose to use other templating syntax for your Vue components if you wish, such as HAML, PUG, JADE, etc.

In Elm, HTML looks nothing like HTML, and for frontend developers, that’s daunting. The combination of various indented levels of divs and square brackets can seem a bit of a mess to manage… and it is. That’s why using the package elm-format in your editor is an essential, otherwise you’re going to spend the bulk of your time indenting things. This package formats Elm to the compiler’s standard on save (or every keystroke if you’re a maniac).

Line length

One thing you’ll immediately notice about the Elm example is that it’s twice the number of lines as the Vue file, but if you look more closely it’s more down to how the Elm compiler dictates the structure of an Elm file. Complex functionality written in Elm files is typically much easier to read — and therefore maintain — than Vue (or any JS alternative in fact).

Storing data and controlling the view

Elm and Vue files both have a similar method for storing data; a “data model” which is used as the source of truth for the UI. Both Elm and Vue can use this data model to dictate the view and to dynamically update it when data changes. This is called data reactivity.

A data model in Elm is defined as:

type alias Model =
    { title : String
    , description : String
    , numberOfPosts : Int

Elm data model

A data model in Vue is defined as:

data: {
  title: "This is the title",
  description: "This is the description",
  numberOfPosts: 12

Vue data model

The Document Object Model (DOM) reacting to JavaScript changes (or model changes) and the JavaScript reacting to DOM changes is called two-way data binding. This is a whole topic on its own that I’ll not go into for now, but it’s definitely worth reading up the terminology and what it means!


I’m not going to do the typical performance comparison, partly out of laziness and the fact your attention is quickly disappearing at this stage. What you do need to know is that both Elm and Vue make use of a Virtual DOM to efficiently batch updates to the DOM when the view needs to be updated based on changes to the data model or vice-versa. If you’re updating the DOM the “Elm way”or “Vue way”, aka via data model binding, then the user’s perception of your UI responsiveness to DOM changes shouldn’t be hindered.


As Elm files tend to follow the same structure and formatting there’s little wriggle room to do your own crazy developer thing, therefore that means coming back to your Elm app later is much easier. It’s also easier for other developers to jump into.

Vue has a bit more freedom, with the majority of JavaScript logic being organised into lifecycle events, but what people write in those events and how they write it is the wild west.

// These are some of the lifecycle events exposed by the Vue framework
beforeCreate() {

created() {

ready() {

mounted() {

updated() {

destroyed() {


Some of the lifecycle events exposed by Vue


In my opinion Vue definitely handles this better. Why? It’s a framework — it’s what it was made for. Elm is a lot more low level and handling everything to do with building multiple components that talk to each other or building a single page application is cumbersome — cumbersome but safe.

Learning Curve

When you first touch Elm you get this entirely new functional computing dictionary thrown in your face. Protect yourself from it (Riot shields are available on eBay). Really though, brace yourself for it if you’re coming from a JavaScript background with no prior experience of functional programming. Like me.

With Vue, the terminology you would have been using with JavaScript is largely the same. You will get some new framework-specific principles and definitions handed to you, though.

Documentation and Package Management

The Elm package documentation is an interesting challenge to navigate. I have found searching on Google can often land you on the wrong version of the documentation for the Elm package you are using, at which point you need to navigate to the correct version internally, which can also be confusing.

Vue follows a more traditional path and delegates how and where package documentation lives and is displayed to package authors.

Both the core Elm and Vue documentation are well organised and written.

To finish

I won’t leave you with a “use this, use that” conclusion, but hopefully some personal opinions above on my experience might help direct a decision, or have sparked an interest in learning Elm, Vue or both! Have fun!

Please feel free to leave a comment if you have any questions!

vue-js vuejs vue javascript Elm

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

8 Popular Websites That Use The Vue.JS Framework

In this article, we are going to list out the most popular websites using Vue JS as their frontend framework. Vue JS is one of those elite progressive JavaScript frameworks that has huge demand in the web development industry. Many popular websites are developed using Vue in their frontend development because of its imperative features.

Vue ShortKey plugin for Vue.js

Vue-ShortKey - The ultimate shortcut plugin to improve the UX .Vue-ShortKey - plugin for VueJS 2.x accepts shortcuts globaly and in a single listener.

A Vue.js wrapper component for Grid.js

A Vue wrapper component for Grid.js. Grid.js is a Free and open-source HTML table plugin written in TypeScript. It works with most JavaScript frameworks.

Vue.js image clipping Components using Vue-Rx

vuejs-clipper .Vue.js image clipping components using Vue-Rx. Add image clipping components to your Vue application in nothing flat. Touch devices supported and fully responsive.

Vue.js JWT Authentication with Vuex and Vue Router

Build a Vue.js JWT Authentication application using Vuex, Vue Router, VeeValidate - JWT authentication with Vue, Vuex, Vue Router that supports VeeValidate