ddraper

Re-usable Vue.js Components with vue-loader

Blog Post created by ddraper on Dec 22, 2016
This is a personal blog post that is primarily intended for tracking my own learning rather than provided to the Alfresco Community for educational purposes. However if you find it useful, informative or have any comments on it then please comment below.

At the end of my last post I had decided to move away from a "Content Distribution" approach for my new Vue.js Alfresco client and move towards a single file component approach. You can view the state of my project at the time of writing by checking out this tag.

 

My original thought was that I would just move my components from the main app.js file into 3 separate files and use ES6 importing and exporting (as now handled by webpack / babel). However as I read through the documentation and various blog posts (including the one I originally started from) I realised that the recommended approach was to use vue-loader either via vueify or the Vue.js CLI.

 

This presented a minor problem in that I already had an established project and didn't want to just start over. Fortunately there are various templates for different build approaches (such webpack as I was using) and it was a relatively simple exercise to install the missing packages defined in the template package.json with yarn and copy across the additional config into my webpack.config.js file.

 

The vue-loader module allows you to write your Vue.js components in files with a .vue extension that are essentially an HTML file containing the following 3 elements:

<style></style>
<template></template>
<script></script>

 

In order to better edit these files I installed a new syntax highlighting package for Sublime Text (which is my editor of choice).

 

I was now able to create a .vue file for each of the 3 components. As an example the smallest is currently ListView.vue:

<style></style>

<template>
   <ul>
      <li v-for="item in list.entries">{{item.entry.name}}</li>
   </ul>
</template>

<script>
   export default {
      props: ['list']
   }
</script>

 

A couple of things that I noticed were that the file name needs to match how I use it as a custom element. I discovered that is is necessary to define your component names in JavaScript  in camel-case (i.e. "ListView") but that you can refer to them in the template as lisp-case (also sometimes referred to as "kebab-case" or "spinal-case") (i.e. "List-View").

 

As predicted I was able to get rid of my global bus (that I had to use with the content distribution approach) so the volume of code actually reduced.

 

The main disadvantage that I can see is that my outer component (List) now directly declares it's sub-components as both dependencies and in it's template:

<template>
   <div>
      <Toolbar :list="list" @pageForward="pageForward" @pageBack="pageBack"></Toolbar>
      <List-View :list="list"></List-View>
   </div>
</template>

 

However, Vue.js does provide a way in which components can be extended (through what they call mixins) which should make it possible to extend List and update the template to use a different view component for example.

Outcomes