Last week I was attending a conference and sat in a good session on Vue.js. I've seen Vue before, even attended another session, but I think I must have paid better attention to this one as I was really impressed with what I saw. In general, my go to JavaScript framework for building applications is Angular, and I really like it. (Despite the painful transition to Angular 2, no wait Angular 3, no wait 4, oh yeah it's just Angular now.) However, if I'm not building an "app" and just using a bit of JavaScript to embellish a page, it feels like overkill.
I'm sure folks can (and do) use Angular in more limited ways, but for me, if I'm not building an entire application with it then it just doesn't feel like a proper fit. This is where Vue really seems to shine though. With Vue, I can do my "non-app" stuff in a much smaller way. You can build complete applications with Vue, but out of the box, it's very light weight. I can see Vue being much more appropriate for the typical thing I do with JavaScript - simple applications that have to work with the DOM and perform updates based on some form of logic.
Don't take my word for it of course - I suggest going through the guide and play with the code there. I'm not trying to write a "How To" guide here since one already exists. What I do want to share though is a quick sample I wrote at the airport this weekend. You should absolutely not take this as a "Best Practice" example. Rather, I just wanted to write a simple application and then rewrite it in Vue.
Ok, so here is the initial, non-Vue code.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
</head>
<body>
<p>
<input type="search" placeholder="Search for name..." id="search">
</p>
<div id="results"></div>
<script>
let API = 'https://openwhisk.ng.bluemix.net/api/v1/web/rcamden%40us.ibm.com_My%20Space/default/nameSearch.json?search=';
let $search, $results;
document.addEventListener('DOMContentLoaded', init, false);
function init() {
$search = document.querySelector('#search');
$results = document.querySelector('#results');
$search.addEventListener('input', doSearch, false);
}
function doSearch(e) {
let term = $search.value;
if(term.length < 3) return;
fetch(API + encodeURIComponent(term))
.then(res => res.json())
.then(res => {
let s = '<ul>';
res.names.forEach((name) => {
s += `<li>${name}</li>`;
});
s += '</ul>';
$results.innerHTML = s;
});
}
</script>
</body>
</html>
The code here is adding an event listener to an input field. On entering text, it performs a search against an OpenWhisk serverless API that simply returns names that match the input. When the result is returned, I then update the DOM with the result.
You can run this sample live right here: https://static.raymondcamden.com/demos/2017/8/7/search1.html
Note that I'm using the Fetch API which is not supported in older browsers. Anything modern though will run it just fine.
Ok, now let's look at the Vue version (and once again, I'm not saying this is the best, or even the "right" implementation):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="myApp" v-cloak>
<p>
<input type="search"
placeholder="Search for name..."
v-model="search"
v-on:input="searchNames">
</p>
<ul>
<li v-for="name in names">{{ name }}</li>
</ul>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
let API = 'https://openwhisk.ng.bluemix.net/api/v1/web/rcamden%40us.ibm.com_My%20Space/default/nameSearch.json?search=';
let myApp = new Vue({
el:'#myApp',
data:{
search:'',
names:[]
},
methods:{
searchNames:function() {
if(this.search.length < 3) return;
fetch(API + encodeURIComponent(this.search))
.then(res => res.json())
.then(res => {
console.log(res);
this.names = res.names;
});
}
}
});
</script>
</body>
</html>
Ok, let's look at the changes. First off, I've created a new Vue app to handle my logic. I love how... I don't know... "compact" this is. I've basically set up the logic for my "as you type/search/render" thing and it's nicely contained on my site. (Of course, normally I'd have this in it's own JS file.)
Next - look at how I assign the event listener to my search field. Using event handlers in HTML is something we moved away from years ago, but the way it is done here feels very nice. I like being able to see my control and note, "Oh there is an event happening when 'input' is fired." Also note the use of v-model
to handle a sync between the value of the field and data in my code.
Now - look at searchNames
. Outside of how I address stuff, this is pretty similar, but, I love that when I'm done, I simply update my local array, and then the rendering takes over.
I love client-side templating (so much so that I wrote a book on it) and having it built-in here works really well.
Finally - the last issue I had to clear up with the "FOUC" (flash of unstyled content) on load, which is done using a v-clock
CSS declaration.
All in all, I think this is roughly the same amount of code, but it felt a heck of a lot easier to use and I especially liked being able to skip all the querySelector and DOM-writing tasks.
Yeah, I keep saying it "feels" good, which isn't very scientific, but if a framework is enjoyable to write, I'm probably going to use the hell out of it. On the flip side, I just don't feel that way about React, and I know React is an incredibly powerful framework, and the hottest thing on the planet now, but I just don't enjoy using it.
Anyway, you can test the Vue version here: https://static.raymondcamden.com/demos/2017/8/7/search2.html
In both cases, try searching for "abe" to see some results. I plan on spending more time learning Vue and blogging on it, and maybe even giving a presentation on it too later this year. I'd love to hear my readers who are using Vue and what they think about it. I'd also love to hear from folks who looked at it and didn't like it. Let me know in the comments below!