Generate Vue Typescript Application - Part 3


Typescript VueJS stutorial

Other articles in the series

  • Making our UI user friendly - Part 15
  • Deploying Phoenix VueJS application using Docker - Part 14
  • Fixing failing Elixir tests - Part 13
  • Adding new features to Order Management - Part 12
  • Add Order Management - Part 11
  • Refactoring and adding tests for Phoenix - Part 10
  • Refactoring VueJS with Typescript- Part 9
  • Add Customer Management - Part 8
  • Writing tests with Jest and Typescript - Part 7
  • Adding Vuex to Vue using Typescript - Part 6
  • Building our Homepage view component - Part 5
  • Add Multi-language support to Vue Typescript - Part 4
  • Generate Vue Typescript Application - Part 3
  • Setting up Models with Ecto and Adding Routing . Part 2
  • Setting up Your Phoenix Application - Part 1
  • Tutorial Series for building a VueJS (Typescript) and Phoenix(Elixir) Shop Management Application - Part 0

  • The front-end related code for this post is available at here.

    Getting started with Vuejs and Typescript

    Typescript is like Javascript with types. Types can help us in finding a category of bugs and help us in refactoring code easily. For setting up a project we use vue-cli 3. To install it, issue the below command.

    npm install -g @vue/cli

    Once we have installed, it is time to create our project.

    Creating the Project

    A new project can be created using vue create.

    vue create shop

    The console will ask a few questions and once it is finished we have a bare minimum working vuejs app. I chose typescript, vue-router, vuex, dart-sass, babel, pwa, unit-jest and e2e-cypress. Once it is finished start the dev server.

    Starting Vue Development Server

    cd shop
    npm run serve

    Now we got the vue running at port 8080.

    Ok, so now we got vue running, but how does it work ?. Lets take a dive into the basic concepts and working of Vue with Typescript.

    Vue starts its execution from the main.ts file inside the src/main.ts file.

    import Vue from 'vue';
    import App from './App.vue';
    import router from './router';
    import store from './store';
    import './registerServiceWorker';
    
    Vue.config.productionTip = false;
    
    new Vue({
      router,
      store,
      render: (h) => h(App),
    }).$mount('#app');

    Routing with Vue-router

    Here we make a new Vue instance with router, store and an app. Router takes care of the routing to views according to the url.

    src/router.ts

    import Vue from 'vue';
    import Router from 'vue-router';
    import Home from './views/Home.vue';
    
    Vue.use(Router);
    
    export default new Router({
      mode: 'history',
      base: process.env.BASE_URL,
      routes: [
        {
          path: '/',
          name: 'home',
          component: Home,
        },
        {
          path: '/about',
          name: 'about',
          // this generates a separate chunk (about.[hash].js) for this route
          // which is lazy-loaded when the route is visited.
          component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
        },
      ],
    });

    Vue Components

    As you can see here when the path is /(root) we route to component Home. Components are self-contained, reusable blocks in Vue. Vue components have a template part, which resides inside <template> tag, where we will write html elements. Another part <style> takes care of the styling and the <script> tag part holds the logic for the component. The files ending with .vue are single-file components. Here we see Home.vue file is imported. Lets see what is inside it, so that we know what we will get when we visit the /.

    <template>
      <div class="home">
        <img src="../assets/logo.png">
        <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
      </div>
    </template>
    
    <script lang="ts">
    import { Component, Vue } from 'vue-property-decorator';
    import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
    
    @Component({
      components: {
        HelloWorld,
      },
    })
    export default class Home extends Vue {}
    </script>

    We see HelloWorld imported from components folder. And it is passed to @Component Typescript decorator. The @Component is a decorator, which tells vue which components are used in the current component, ie. inside Home component. Since we only use the HelloWorld, we list it there. And we use the HelloWorld component inside the <template> tag. It is like embedding the contents of that component, inside our own. You can consider it as small building blocks which make up our current view.

    Lets look at the HelloWorld component itself. I omitted unimportant pieces below, like styling information and links.

    <template>
      <div class="hello">
        <h1>{{ msg }}</h1>
      </div>
    </template>
    
    <script lang="ts">
    import { Component, Prop, Vue } from 'vue-property-decorator';
    
    @Component
    export default class HelloWorld extends Vue {
      @Prop() private msg!: string;
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped lang="scss">
    </style>

    Vue Component Props

    Here we see a new decorator, the @Prop decorator. It is another decorator for making use of vue props. Props are messages which we pass to the components. For example here we see that we are using {{msg}} inside our <template>, but we haven’t assigned a value to it anywhere in our component. So from where, will we get this value ?. The props is the answer. Component which embeds this components provides it to us via props. In this case the Home component gives it to us like below. Notice the msg=…value.

    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>

    So our {{msg}} gets the value Welcome to Your Vue.js …..

    State management in Vue

    Store is like a database where you store data from components. The store we use here Vuex is a reactive store, which means all components which use a specific data will be automatically updated, if that data changes.

    src/store.ts

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      state: {
    
      },
      mutations: {
    
      },
      actions: {
    
      },
    });

    We will discuss the state, mutations and actions in a later part of the tutorial. If we notice the main.ts file, it passes the App.vue into the render function and mounts it to #app id in the public/index.html file. This means App.vue is the main/entry file.

    <template>
      <div id="app">
        <div id="nav">
          <router-link to="/">Home</router-link> |
          <router-link to="/about">About</router-link>
        </div>
        <router-view/>
      </div>
    </template>
    <script></script>
    <style></style>

    Inside the App.vue file we have two router-links. The router-link is a like a a href for router. router-link modifies the router view based on this link in accordance with the router.ts we discussed earlier. This results in changing of displayed component when the link is clicked. This can be seen by clicking the About button, which points to /about path, which is mapped to views/About.vue component inside router.ts.

    The only step left is to mount the vue to some tag in HTML file, which is done by the $mount. Here it mounts to tag with id #app. Head over to Official docs for an in depth explanation of Vue. The source code for client is available here.

    In next part, we will discuss about adding multi language support to Vue.