notoriousb1t

MVP Part 3: VueJS

For weeks I have been building a project called Model View Pizza. It is a simple page that customizes a pizza and lets the user see it being built as each selection is made. I plan to build this same application in at least ten of the more popular JavaScript MV* frameworks in twenty weeks.

I decided to make the third framework VueJS. It seems to have a very organized structure and a very prescriptive way of building web apps.

What is VueJS

VueJS is an MVVM (Model View ViewModel) framework that uses a presenter (ViewModel) to separate the concerns of the state/information (Model) from the html (View). VueJS was released by Evan You last year in February and has enjoyed some success at adoption.

Getting Started

VueJS is not that new to me. I have used it in a few projects at work, but have had to replace it with KendoUI because I could never get jQuery datepickers or KendoUI datapickers to work quite right with VueJS in our applications. In business applications, datepickers are an essential widget, so I haven't been able to use it in production.

When the team first starting using VueJS, the reaction was pretty mixed. One of the guys who used WPF (Windows Presentation Framework) a lot in a previous job really, really liked the framework a lot. Another team member, however, had a hard time getting used to VueJS because it is so opinionated. There is a bucket for everything and that was difficult to adjust to. Sadly though, when he finally get used to the framework, I had to move away from it because we were not able to successfully get an application finished with it for the second time without over-complicating the code. This isn't a negative reflection of the framework; it is just what how it worked out for us.

Despite all of this, I really do like this framework. It is well tested, it has great (not just good) documentation, and it has a lot of good ideas in how to make a webpage interactive.

A Simple Example

Without further ado, here is a simple example of VueJS:

See the Pen VueJS Simple Example by Christopher Wallis (@notoriousb1t) on CodePen.

In the CodePen example, VueJS initializes the ViewModel by passing options to a new Vue object. The el property can either be a CSS selector or can be an HTMLElement. This is good because it allows me to either pick out an element to initialize or provide an object directly. The data property provides an initial object to serve as the model. I can access these fields either from this (they are proxied there) or through the this.$data object within the methods. The methods property allows me to define functions to be used as events or just plain methods to call from other methods.

VueJS has a property for most things out of the box. It has a watch property that will fire a method when a property changes, it has a computed property for model values that derive from other values, and it has life-cycle events such as created to run code at certain milestones of its execution. There are a bunch more, but it would take me pages and pages to explain them all.

Development

During development I found myself having to constantly look at the documention to figure out where to put something. I can imagine that this would present a steep learning curve for teams adopting a client-side framework. Here are some highlights:

Select Lists

The select lists were not difficult to setup at all. When I needed to bind a value to a select or input, I just put the v-model directive on it with the name of the field. What struck me as odd was the fact that the attribute to supply select with options was just options. I expected it to be v-options since every other directive is prefixed with a v-.

    data: {
        options: options,
        // ...
        size: initial.size,
        // ...
    },

    <div class="form-group">
        <h3>Pick a Size</h3>
        <select v-model="size" 
            options="options.sizes" 
            class="ddl" 
            aria-label="Pick a size">
        </select>
    </div>

The Toppings

Getting the topping checkbox list to work properly is probably the most challenging part of this project for any framework. In AngularJS 1, I was able to use click events to select and deselect toppings. In KnockoutJS, there was a built in way to handle checkbox lists. With neither a built in way nor the ability to easily do this through click events, I figured out a way using computed properties.

    computed: {
        /// ...
        toppings: function () {
            return this.toppingSelections
                .filter(function (topping) { return topping.selected; })
                .map(function (topping) { return topping.value; });
        }
    },
    data: {
        // ... 
        toppingSelections: options.toppings.map(function (topping) {
            return {
                value: topping,
                selected: false
            };
        })
    },

In the JavaScript above, I created an array of objects with each topping name plus a selected property and then bound that to the nested template in the Html below.

    <div v-if="isStepToppings">
        <h3>Customize Your Toppings!</h3>
        <dl class="checkboxlist-inline">
            <dd v-repeat="toppingSelections" class="checkbox">
                <label>
                    <input type="checkbox" v-model="selected" />
                    <span v-text="value"></span>
                </label>
            </dd>
        </dl>
    </div>

When I need an array of topping names, I can access the computed topping field. When I need to select a topping, I can go to toppingSelection and set selected to true.

Overall Impression

VueJS is a very well thought out framework with the potential to build composable applications. I think that in the long run VueJS may facilitate very stable applications, but that there is definitely a large ramp up time. I think that while it may be too rigid for my workplace, that it is probably viable for most.