I have always been a fan of simplicity when it comes to js frameworks. I guess that’s one of the reasons that Aurelia appeals to me. However, frameworks are inherently complex. They are usually opinionated (that’s part of the point of a framework, right?) and make a lot of decisions for you. The benefit is of course that many of the architectural design desicions are already taken and you (as a developer) can simply focus on writing code.
That said, a framework is not always the right choice. There’s been some heated debate on this over the years, but I tend to agree with Sean at planningforaliens in the statement
Using a JS framework should never be your default decision.
Instead focus on what you want to achieve and use the right tools to do just that and nothing more.
I’ve been a long time fan of Knockout.js. It’s been around for a long time, it’s small (~22kb min+gz), it’s simple and it gets the job done. It does not bring uneccessary bloat to my code base. I’ve used it for lots of projects and never been dissatisfied. Lately though I’ve been working with Vue.js more and more. Almost everything that has irked me slightly about Knockout, Vue does better, faster and simpler.
In this article I'm using the release candidate of version 2.0 of Vue. All of the code in this article is 100% backwards compatible with Vue 1.0 though.
Here are a few examples.
Much cleaner and simpler in Vue in my opinion. Calling the
document.getElementBydId is a nuisance, especially when unit testing.
A bit more verbose in Vue, but again, much cleaner and the separation of methods and data makes it easy to find what you’re looking for when you have a complex model. You also do not need to wrap your properties in a
ko.observable call. This is good but does have some drawbacks in terms of browser compatability. I’ll get back to that.
The difference here is not huge and not as apparent as it would be if we had several properties. Lets compare a slightly more complex example.
As you can see Knockout puts all its databinding in one attribute
data-bind which makes it hard to read when the different bindings start to pile up. Vues syntax is a bit more verbose, but you can use shorthands to make the attributes very unobtrusive.
Object.DefineProperty. Vue traverses the entire data object and converts every property into getters and setters using
Object.DefineProperty adding logic to each for change-notification and dependency-tracking.
Object.DefineProperty is an ECMAScript 5 feature and thus not available in older browsers such as IE 8. So if you're stuck having to support such ancient browsers for some unfathomable reason then you're out of luck with Vue and we all pity you.
We can actually observe this happening in our console if we inspect the vue data object:
Notice how the properties are actually get/set methods instead of primitive values?
If you want to delve even deeper into how Vue applies change tracking there’s an excellent article in the official docs.
Lets build something
Okay, so we have scratched the surface of Vue. Now lets build something where we put it all together.
We implement an html snippet that will contain our list of villains, using the
On the input we make use of the
@keyup binding (remember
@ is the shorthand for
v-on:) with an event modifier
.enter. This means we’re listening specifically for when a user hits the enter key on our input. A very convenient way of abstracting away the boilerplate code of
if(e.keyCode === 13). Vue provides several very handy event modifiers.
The model instance then provides the view with the data it needs and a handler for the keyup event.
Notice how we use the
v-model attribute to bind the input to the newVillainName property. This is actually nothing more than syntactic sugar for the more verbose
<input v-bind:value="newVillainName" v-on:input="newVillainName = $event.target.value">.
Components components components
If you’ve been working with Knockout in the past chances are that you’ve created your fair share of Knockout components. Reusable, small widgets with a custom tag name that can contain their own view and model. Vue has the same concept and in fact takes it a bit further with single file components that encapsulate everything from the html template to the css in a single self contained file.
Lets consider our example above briefly. How can we extract the presentation and logic of a villain away from the list presenting it? Lets turn it into a component!
To register a component globally (we won’t be looking at local components in this post, maybe another one) we call the
Vue.component method like this:
This component can then be used in our html like this:
data needs to be a function for components. This is to make sure that each component gets its own instance of the data object, otherwise they would share state and changes to one would update all components of the same type!
Another interesting thing is the
props property, this is how we pass data to our component from an outside scope. In our case we pass the data about the villain to our component and later use that to set the properties of our component. This is not strictly necessary, we could use our
villainData directly in our component like this:
This would make sure that any changes to the
villainData made by the parent would flow down to the child component. However as objects are passed by reference any changes made to the
villainData by the child would mutate the object for the parent as well and this might cause unwanted side effects. Vue will actually warn you if you try to mutate a prop inside a child component.
In our simple case it makes no big difference, but it’s important to understand the distinction.
Our complete example with a component would now look something like this:
We could now proceed to add logic and update the view for the villain component separately and without affecting our main model instance.
Our example component above would look something like this as a
How does it compare?
So how does Vue stand up to other popular frameworks and libraries such as Ember, React and Angular? There’s a great comparison already on the vue.js official site that you can find here. This is of course slightly biased as it’s written by people already invested in Vue. However, numbers just don’t lie, have a look at this speed and memory comparison of most of the popular frameworks.
As you can see Vue is one of the best in class and faster than both Angular, Angular2, Aurelia, Ember and React.
So, it’s fast, simple, small and powerful and this article barely scratched the surface. There’s lots and lots more to look at: mixins, custom directives, computed properties, filters, unit testing etc. but enough for one day (or post). I’m sure I’ll get back to many of these concepts in future blog posts.
Now, do you Vue yet?