- vuejs 2017-03-19T16:58:15+01:00 https://fadeit.dk/blog/tag/vuejs.html Getting started with Vue.js: AngularJS perspective 2015-05-14T15:14:03+02:00 https://fadeit.dk/blog /2015/05/14/getting-started-with-vuejs-angularjs-perspective <h2 id="background">Background</h2> <p>First and foremost, what is Vue.js and why should you use it?</p> <p>Vue is a library for developing interactive web interfaces. Its API is inspired by Angular &amp; Backbone, but you can read more about it in <a href="http://vuejs.org/guide/">this guide</a>. What’s more interesting is <u>why use it</u>, especially when you are familiar with Angular. First of all, it’s very flexible. It allows mixing and matching all the libraries you love. That means you can create your own little front-end stack. Secondly, it’s more snappy because it’s simpler and doesn’t use dirty checking to observe changes. On top of that, learning Vue doesn’t take much time. This will make it easy to bring in new team members.</p> <p>You can read even more about it in Vue’s <a href="http://vuejs.org/guide/faq.html">FAQ page</a>, where Vue is compared to Angular, React and more. <br /><small><strong>Updated 15 May 2015</strong></small></p> <p>I jumped on the AngularJS train more than 1 year ago and had lots of fun working with it. From August to January 2015 I had the chance to research Angular application structures. The study was in relation to performance, but it touched on many other subjects, such as component reusability and learnability.</p> <p>I am new to Vue.js, therefore this article will be about my first encounter with the library. Later on I will try to make a more comprehensive analysis.</p> <blockquote> <p>Angular <b class="title">1.*</b> and Vue.js <b class="title">0.11</b> are considered in the article. Breaking changes might come in <a href="https://github.com/vuejs/Discussion/issues/158">Vue 0.12</a>. As for Angular, version 2 will be a completely different beast.</p> </blockquote> <h2 id="vuejs-and-angularjs">Vue.js and AngularJS</h2> <p>I felt comfortable with Vue within a few days. It might be because it resembles other frameworks. It might be because of its simplicity, I couldn’t tell. To better portray the similarities &amp; differences between the two, I devised a brief comparison of some of the high-level concepts in Angular and Vue. Here’s what I ended up with:</p> <table class="fdt-table"> <thead> <tr> <th>AngularJS</th> <th>Vue.js</th> <th>Notes</th> </tr> </thead> <tbody> <tr> <td style="width: 33.33333%;"> <b class="title">Angular Modules</b> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="s1">'myModule'</span><span class="p">,</span> <span class="p">[...]);</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Vue components</b> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">Vue</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span> <span class="na">data</span><span class="p">:</span> <span class="kd">function</span><span class="p">(){</span> <span class="k">return</span> <span class="p">{...}</span> <span class="p">},</span> <span class="na">created</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{...},</span> <span class="na">ready</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{...},</span> <span class="na">components</span><span class="p">:</span> <span class="p">{...},</span> <span class="na">methods</span><span class="p">:</span> <span class="p">{...},</span> <span class="na">watch</span><span class="p">:</span> <span class="p">{...}</span> <span class="c1">//(other props excluded)</span> <span class="p">});</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Module notes</b><br /> Modules are a container in Angular, holding other entities such as controllers, directives, etc. In Vue they hold most component logic. </td> </tr> <tr> <td style="width: 33.33333%;"> <b class="title">Vue directives</b><br /> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">myModule</span><span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="s1">'directiveName'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">injectables</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">{</span> <span class="na">restrict</span><span class="p">:</span> <span class="s1">'A'</span><span class="p">,</span> <span class="na">template</span><span class="p">:</span> <span class="s1">'&lt;div&gt;&lt;/div&gt;'</span><span class="p">,</span> <span class="na">controller</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="p">},</span> <span class="na">compile</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{...},</span> <span class="na">link</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="p">}</span> <span class="c1">//(other props excluded)</span> <span class="p">};</span> <span class="p">});</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Angular directives</b><br /> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">Vue</span><span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="s1">'my-directive'</span><span class="p">,</span> <span class="p">{</span> <span class="na">bind</span><span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{...},</span> <span class="na">update</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">newValue</span><span class="p">,</span> <span class="nx">oldValue</span><span class="p">)</span> <span class="p">{...},</span> <span class="na">unbind</span><span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{...}</span> <span class="p">});</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Directive notes</b><br /> Directives are not as powerful in Vue; they seem to be more focused. In Angular a directive can be many things, better resembling a component in the Vue world. </td> </tr> <tr> <td style="width: 33.33333%;"> <b class="title">Vue filters</b><br /> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">myModule</span><span class="p">.</span><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="err">‘</span><span class="nx">filterName</span><span class="s1">', []) .filter('</span><span class="nx">reverse</span><span class="err">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">input</span><span class="p">)</span> <span class="p">{...};</span> <span class="p">});</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Angular filters</b><br /> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">Vue</span><span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="s1">'reverse'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){...};</span> <span class="p">});</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Filter notes</b><br /> Filters aren’t much different, although Vue provides read/write options. (see <a href="http://vuejs.org/guide/custom-filter.html" target="_blank">this guide</a>) </td> </tr> </tbody> </table> <p>Because Vue will only help us manage the VM, it won’t tackle some of the challenges that Angular covers out of the box. Services / HTTP reqs, routing, promises (just to name a few) are not among Vue’s concerns. That’s good and bad. Perhaps “bad” is an exaggeration; but it’s a negative aspect for someone that got used to Angular and didn’t have to lift a finger for it. In other words, we have to mix and match libraries as we go to cover our needs. That can be quite a task, but some developers love having this kind of control (others think it’s a waste of time). However, once you find a few good libraries, you won’t have to do it again. I think this kind of flexibility is very empowering. Imagine building your own smaller, focused framework (like Angular) on top of a good foundation: Vue.</p> <p>Creating a personalized front-end stack is great fun too. The first stack I ended up with was made out of: Director (routing), Reqwest (you guessed it), Q (promises) and of course Vue. The best name I can make out of these is QRVD (kinda sounds like curved). For the rest of the article you could have this stack in mind, although it won’t change much if you don’t.</p> <h2 id="templating">Templating</h2> <p>For the same reasons that’s easy to write templates in Angular, it’s really easy to write them in Vue. In fact, it’s a bit of a struggle to find differences between the two.</p> <p>Here’s an overview:</p> <table class="fdt-table"> <thead> <tr> <th>AngularJS</th> <th>Vue.js</th> <th>Notes</th> </tr> </thead> <tbody> <tr> <td style="width: 33.33333%;"> <b class="title">Angular interpolation</b> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">{{</span><span class="nx">myVariable</span><span class="p">}}</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Vue interpolation</b> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="p">{{</span><span class="nx">myVariable</span><span class="p">}}</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Interpolation notes</b><br /> Interpolating an object or array won't work out of the box in Vue ([Object] will be displayed). I always found that useful for debugging in Angular. Vue does come with a built-in json filter for it though: </td> </tr> <tr> <td style="width: 33.33333%;"> <b class="title">Angular model binding</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">ng-model=</span><span class="s">"myVar"</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">ng-bind=</span><span class="s">"myVar"</span><span class="nt">&gt;&lt;/p&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Vue model binding</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">v-model=</span><span class="s">"myVar"</span><span class="nt">&gt;</span> <span class="nt">&lt;p</span> <span class="na">v-model=</span><span class="s">"myVar"</span><span class="nt">&gt;&lt;/p&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"></td> </tr> <tr> <td style="width: 33.33333%;"> <b class="title">Angular Loops</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;li</span> <span class="na">ng-repeat=</span><span class="s">"item in items"</span> <span class="na">class=</span><span class="s">"item-{{$index}}"</span><span class="nt">&gt;</span> {{item.myProperty}} <span class="nt">&lt;/li&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Vue Loops</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;li</span> <span class="na">v-repeat=</span><span class="s">"items"</span> <span class="na">class=</span><span class="s">"item-{{$index}}"</span><span class="nt">&gt;</span> {{myProperty}} <span class="nt">&lt;/li&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Loop notes</b><br /> Both support model options (ex. debounce for a loop filter). BTW, we can also assign repeated objects in Vue, like in Angular:<br /> <b>v-repeat='item: items'</b> </td> </tr> <tr> <td style="width: 33.33333%;"> <b class="title">Angular conditionals</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">ng-if=</span><span class="s">"myVar"</span><span class="nt">&gt;&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">ng-show=</span><span class="s">"myVar"</span><span class="nt">&gt;&lt;/div&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Vue conditionals</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">v-if=</span><span class="s">"myVar"</span><span class="nt">&gt;&lt;/div&gt;</span> <span class="nt">&lt;div</span> <span class="na">v-show=</span><span class="s">"myVar"</span><span class="nt">&gt;&lt;/div&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"></td> </tr> <tr> <td style="width: 33.33333%;"> <b class="title">Angular conditional classes</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">ng-class=</span><span class="s">"{‘active’: myVar}"</span><span class="nt">&gt;&lt;/div&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Vue conditional classes</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">v-class=</span><span class="s">"active: myVar"</span><span class="nt">&gt;&lt;/div&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Conditional classes notes</b><br /> Another example that shows similarities. <br /> Both also support <b>v-attr/ng-attr</b>. </td> </tr> <tr> <td style="width: 33.33333%;"> <b class="title">Angular event binding</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">ng-click=</span><span class="s">"myMethod($event)"</span><span class="nt">&gt;&lt;/div&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Vue event binding</b><br /> <figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;div</span> <span class="na">v-on=</span><span class="s">"click: myMethod($event)"</span><span class="nt">&gt;&lt;/div&gt;</span></code></pre></figure> </td> <td style="width: 33.33333%;"> <b class="title">Event binding notes</b><br /> The generic <b>v-on</b> directive makes things more consistent than in Angular, but I guess it's down to personal preference. </td> </tr> </tbody> </table> <p>The list goes on. There’s even a v-cloak directive that hides the bindings before they are rendered (as ng-cloak does).</p> <p>However, there’s one directive that you won’t find in Angular: <code class="highlighter-rouge">v-with</code>. Attaching this directive and passing a data object will allow a child VM to inherit data from his parent. In my first encounter, I though of it as a drastically simplified Angular Controller, managing the data flow across the application (without the need of an equivalent to <code class="highlighter-rouge">$scope</code>. By default, components will have an isolated scope. That makes this directive essential, although components also accept <em>inherit</em> as a property (see <a href="http://vuejs.org/guide/components.html#Scope_Inheritance">more on scope inheritance</a>).</p> <h2 id="modularity--application-structures">Modularity / Application structures</h2> <p>As I mentioned, I researched this area in Angular. My conclusion was that Angular both nailed it and it didn’t. You can create great modular architectures that are indeed maintainable, reusable, comprehensible, etc. However, you’ll need a monster-build strategy to go with it, or perhaps use tools like <a href="http://requirejs.org/">Require.js</a> or <a href="http://browserify.org/">Browserify</a> to ease the pain. That’s not even the worst part. If you are just starting with Angular, you probably won’t come across a good structuring guide, which is a shame. It’s only later (or maybe too late) that Angular developers decide to look into it.</p> <p>So how does Vue.js perform? More or less the same. There’s a very short section in the <a href="http://vuejs.org/guide/application.html">Vue guide</a> about app structuring, but it’s not enough. I believe developers are able to produce kick-ass modular architectures with Vue, but there are no comprehensive guides or suggestions on how to do it. I wasn’t satisfied, so in the ‘Building larger applications’ section I tried to sketch out an example that may help developers new to Vue.</p> <h2 id="components">Components</h2> <p>Before that, I have to add a comment on components. I think, Vue managed to clearly separate components, which we can’t really say about Angular. It’s perhaps closer to Angular 2, which is great news in my mind. <br /> As a result, there’s no need for a <code class="highlighter-rouge">$scope</code> equivalent.</p> <h2 id="scopes--data-flow">Scopes / Data flow</h2> <p>I truly believe Vue is elegant when it comes to Data flow &amp; control. It felt natural and there was no need for an emit/broadcast mechanism to communicate with parent components (although Vue supports such events). There is a downside to it: the components and views become even more coupled (but hey, it is called a VM). Sometimes it’s tricky to understand which data is inherited from which <code class="highlighter-rouge">v-with</code>, so use it sparingly. There are ways to prevent spaghetti code from creeping in. Services are one good method, but there’s not much documentation about them.</p> <h2 id="services">Services</h2> <p><em>My source is written in CoffeeScript, so I’ll provide examples in both Coffee and Vanilla JS format.</em></p> <p>One approach for writing services is to use a <code class="highlighter-rouge">HTTP</code> -&gt; <code class="highlighter-rouge">Service</code> -&gt; <code class="highlighter-rouge">Component</code> mechanism. HTTP has to be generic, so we can extend it for each object:</p> <table class="fdt-table"> <thead> <tr> <th>CoffeeScript</th> <th>JavaScript</th> </tr> </thead> <tbody> <tr> <td style="width: 50%;"> <figure class="highlight"><pre><code class="language-coffeescript" data-lang="coffeescript"><span class="k">class</span> <span class="nx">HTTP</span> <span class="na">constructor</span><span class="o">:</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="p">...</span> <span class="na">get</span><span class="o">:</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="p">...</span> <span class="na">post</span><span class="o">:</span> <span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">...</span> <span class="na">delete</span><span class="o">:</span> <span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">...</span> <span class="na">patch</span><span class="o">:</span> <span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">...</span></code></pre></figure> </td> <td style="width: 50%;"> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">HTTP</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="nx">HTTP</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">get</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{...};</span> <span class="nx">HTTP</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">post</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{...};</span> <span class="nx">HTTP</span><span class="p">.</span><span class="nx">prototype</span><span class="p">[</span><span class="s2">"delete"</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="p">{...};</span> <span class="nx">HTTP</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">patch</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span> <span class="p">{...};</span> <span class="k">return</span> <span class="nx">HTTP</span><span class="p">;</span> <span class="p">})();</span></code></pre></figure> </td> </tr> </tbody> </table> <p>Just for reference, a patch request using reqwest looks like this:</p> <div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="nx">reqwest</span><span class="p">({</span> <span class="na">url</span><span class="p">:</span> <span class="nx">url</span><span class="p">,</span> <span class="na">type</span><span class="p">:</span> <span class="s1">'json'</span><span class="p">,</span> <span class="na">method</span><span class="p">:</span> <span class="s1">'patch'</span><span class="p">,</span> <span class="na">data</span><span class="p">:</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">data</span><span class="p">),</span> <span class="na">contentType</span><span class="p">:</span> <span class="s1">'application/json'</span> <span class="p">});</span> </code></pre> </div> <p>With CoffeeScript we can extend the HTTP class to adapt it for other use cases. For example, the User object could look like: <br /> (Remember: Angular already has the $http service, so we don’t have to do any of these bits)</p> <table class="fdt-table"> <thead> <tr> <th>CoffeeScript</th> <th>JavaScript</th> </tr> </thead> <tbody> <tr> <td style="width: 50%;"> <figure class="highlight"><pre><code class="language-coffeescript" data-lang="coffeescript"><span class="k">class</span> <span class="nx">UserHTTP</span> <span class="k">extends</span> <span class="nx">HTTP</span> <span class="na">all</span><span class="o">:</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="vi">@</span><span class="na">get</span><span class="p">(</span><span class="s">"/v1/users"</span><span class="p">)</span> <span class="na">remove</span><span class="o">:</span> <span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="vi">@</span><span class="na">delete</span><span class="p">(</span><span class="err">“</span><span class="c1">#{/v1/users/#{id}”)</span> <span class="c1">#...</span></code></pre></figure> </td> <td style="width: 50%;"> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">UserHTTP</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">superClass</span><span class="p">)</span> <span class="p">{</span> <span class="nx">extend</span><span class="p">(</span><span class="nx">UserHTTP</span><span class="p">,</span> <span class="nx">superClass</span><span class="p">);</span> <span class="kd">function</span> <span class="nx">UserHTTP</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">UserHTTP</span><span class="p">.</span><span class="nx">__super__</span><span class="p">.</span><span class="nx">constructor</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span> <span class="p">}</span> <span class="nx">UserHTTP</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">all</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">"/v1/users"</span><span class="p">);</span> <span class="p">};</span> <span class="nx">UserHTTP</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">remove</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="err">“</span><span class="o">/</span><span class="nx">v1</span><span class="o">/</span><span class="nx">users</span><span class="o">/</span><span class="err">“</span> <span class="o">+</span> <span class="nx">id</span><span class="p">);</span> <span class="p">};</span> <span class="c1">//...</span> <span class="k">return</span> <span class="nx">UserHTTP</span><span class="p">;</span> <span class="p">})(</span><span class="nx">HTTP</span><span class="p">);</span></code></pre></figure> </td> </tr> </tbody> </table> <p>Then come the actual services, which are perhaps closer to what we’re used to in Angular. For the same Object, we need to pass UserHTTP as a constructor param and then we’ll be able to call its methods and process the data as needed (before or after requests are sent).</p> <table class="fdt-table"> <thead> <tr> <th>CoffeeScript</th> <th>JavaScript</th> </tr> </thead> <tbody> <tr> <td style="width: 50%;"> <figure class="highlight"><pre><code class="language-coffeescript" data-lang="coffeescript"><span class="k">class</span> <span class="nx">UserService</span> <span class="na">constructor</span><span class="o">:</span> <span class="p">(</span><span class="vi">@</span><span class="na">HTTP</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="na">all</span><span class="o">:</span> <span class="p">()</span> <span class="o">-&gt;</span> <span class="vi">@</span><span class="na">HTTP</span><span class="p">.</span><span class="na">all</span><span class="p">()</span> <span class="na">remove</span><span class="o">:</span> <span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="c1"># Here we can do some data processing</span> <span class="c1"># ...</span> <span class="vi">@</span><span class="na">HTTP</span><span class="p">.</span><span class="na">remove</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span></code></pre></figure> </td> <td style="width: 50%;"> <figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">UserService</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="kd">function</span> <span class="nx">UserService</span><span class="p">(</span><span class="nx">HTTP</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="p">.</span><span class="nx">HTTP</span> <span class="o">=</span> <span class="nx">HTTP</span><span class="p">;</span> <span class="p">}</span> <span class="nx">UserService</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">all</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{...};</span> <span class="nx">UserService</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">remove</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//Here we can do some data processing</span> <span class="c1">//...</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">HTTP</span><span class="p">.</span><span class="nx">remove</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span> <span class="p">};</span> <span class="k">return</span> <span class="nx">UserService</span><span class="p">;</span> <span class="p">})();</span></code></pre></figure> </td> </tr> </tbody> </table> <p>Finally, in any component we can instantiate a service and call the methods that in turn will make an HTTP request.</p> <div class="language-javascript highlighter-rouge"><pre class="highlight"><code><span class="p">...</span> <span class="nx">HTTP</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HTTP</span><span class="p">();</span> <span class="nx">userService</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">UserService</span><span class="p">(</span><span class="nx">HTTP</span><span class="p">.</span><span class="nx">users</span><span class="p">);</span> <span class="p">...</span> <span class="c1">// Inside a Vue component</span> <span class="p">...</span> <span class="nl">ready</span><span class="p">:</span> <span class="kd">function</span><span class="p">(){</span> <span class="nx">vm</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span> <span class="nx">userService</span><span class="p">.</span><span class="nx">all</span><span class="p">()</span> <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">users</span><span class="p">){</span> <span class="nx">vm</span><span class="p">.</span><span class="nx">$set</span><span class="p">(</span><span class="s1">'users'</span><span class="p">,</span> <span class="nx">users</span><span class="p">);</span> <span class="p">});</span> <span class="p">...</span> </code></pre> </div> <p>The next section contains a diagram that illustrates how this all fits together.</p> <h2 id="building-larger-applications">Building larger applications</h2> <p>First of all, what is a large app? Well, potentially any app can become large. When it’s hard to understand how things are working and the structure is not comprehensible for outsiders, then you’re probably dealing with a large app.</p> <p>In my case, after about a week of working on a Vue application the structure was almost chaotic. It wasn’t easy to tell how it all fits together. On one hand, components weren’t properly separated, but this doesn’t have anything to do with Vue. So it was time for taking a step back, analyzing and refactoring. I sketched out my components and tried to create a structure that would make things better.</p> <p>Before you check out the diagram below, it is worth mentioning that Browserify was used to split components up. As I said before, you can either follow this approach or create a build strategy with Gulp/Grunt that concatenates the files. <br /><br /> Get a full copy of the diagram <a href="/blog/assets/getting-started-with-vuejs-angularjs-perspective/vue-large-app-structure-diagram.svg">here</a>.</p> <p><img src="/blog/assets/getting-started-with-vuejs-angularjs-perspective/vue-large-app-structure-diagram.svg" alt="Diagram: one way to structure larger Vue.js apps." /></p> <p>In terms of file/directory structure, here’s how a Vue app could look like:</p> <p>(get a full copy <a href="/blog/assets/getting-started-with-vuejs-angularjs-perspective/vue-large-app-directory-structure.svg">here</a>)</p> <p><img src="/blog/assets/getting-started-with-vuejs-angularjs-perspective/vue-large-app-directory-structure.svg" alt="Possible directory structure for a larger Vue.js app." /></p> <h2 id="final-words">Final words</h2> <p>I hope these sketches will be a good starting point/source of inspiration for devs that are starting out.</p> <p>In future posts I’ll probably write more about testing, maintainability and scalability, if I discover something interesting.</p> <p>My final words are: try out Vue, you might find it useful for many of your projects. It’s a nice little library with as many super powers as Angular!</p>