Hamidreza Amini

Hamidreza Amini

JavaScript Engineer

  • Residence:
    Iran
  • City:
    Shiraz
  • Year of birth:
    1993

Languages

100%

Persian

70%

English


Coding

JavaScript

90%

TypeScript

90%

React

90%

NodeJs

70%

Web3.js

70%

React Native

40%

HTML, CSS, SASS

90%

C#, ASP.NET

70%


Knowledge
  • Linux (Ubuntu)
  • SOLID Principles
  • Redux, GatsbyJS
  • ExpressJs, PassportJs
  • MongoDb, Mongoose
  • Stylus, SASS, SCSS
  • GIT Version Control

Using Vue with Typescript and JSX

Why Typescript and JSX?

Hi everyone,
I like using typescript and JSX in front-end development, that’s why I was attracted to React. But you can use class component, with typescript and JSX in developing your front-end with Vue. In this post I want to show you how to do it.

Vue is introduced a preset and a plugin for babel in its third version which is letting you to create your vue components easier with typescript and render your view with JSX.

Getting Start

Installing the requirements for Vue, JSX and Typescript

First of all, you need to install the vue 3+, vue-class-component 8+, babel 7+, vue cli and typescript:

npm i vue@^3.0.0
##
npm i vue-class-component@^8.0.0-rc
##
npm i @babel/core
##
npm i @vue/cli
##
npm i typescript

After that you should install webpack, webpack-cli, webpack-dev-server ( if you don’t have any specific server ), babel-loader and ts-loader:

npm i webpack
##
npm i webpack-cli@3.3.11
##
npm i webpack-dev-server
##
npm i babel-loader
##
npm i ts-loader

For using JSX in your components, you need to install the following packages:

npm i @vue/babel-preset-app
##
npm i @vue/babel-plugin-jsx

Configurations

And then configure your .babelrc file like this:

{
  "presets": ["@vue/babel-preset-app"],
  "plugins": ["@vue/babel-plugin-jsx"]
}

Then, create the webpack.config.js file in your root and use the following config:

const { join } = require('path');

module.exports = {
  mode: 'development',
  target: 'web',
  entry: join(__dirname, './app/index.tsx'),
  output: {
    filename: 'bundle.js',
    path: join(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.(ts|tsx)/,
        exclude: /node_modules/,
        use: [{ loader: 'babel-loader' }, { loader: 'ts-loader' }]
      }
    ]
  },
  watch: true,
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx', '.styl']
  },
  devServer: {
    contentBase: join(__dirname, './app'),
    compress: true,
    port: 9000,
    publicPath: '/dist/'
  }
};

Also you should configure your tsconfig.json file as below:

{
  "compileOnSave": true,
  "compilerOptions": {
    "experimentalDecorators": true,
    "target": "esnext",
    "strict": true,
    "module": "ESNext",
    "moduleResolution": "node",
    "jsx": "preserve",
    "strictPropertyInitialization": false
  },
  "exclude": ["node_modules"]
}

Start creating vue components with JSX and typescript

Then create a folder called app ( or any other name that you like, but you should remember to use the correct direction for your entry in webpack.config.js file) and create your first component in this folder like this:

import { Vue } from "vue-class-component";

export class Home extends Vue {
  public render(): any {
    return <p>Hello world!!, this is our first vue component with JSX</p>;
  }
}

Now we need an HTML file that I called it index.html and put it in app folder: ( you can use a different name or put it in a different folder, but remember to change the devSever configuration of your webpack.config.js file)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="/dist/bundle.js"></script>
  </body>
</html>

Now you just need an entry point which is a file in app folder, called index.tsx. You should pass your main component to createApp function and then mount it to any specific element of your DOM. Here we are mounting it to an element that its ID is “root”:

import { createApp } from "vue";
import { Home } from "./home-component";

createApp(<Home />).mount("#root");

Then you can add the start script to your package.json as the following:

{
  ...
  "scripts": {
    "start": "webpack-dev-server"
  },
  ...
}

After that use the following command:

npm start

For using properties in your component, you need to create a class and use it in your component like this:

import { prop } from "vue-class-component";

export class UserInfoProperties {
  public name: string | undefined = prop({ type: String });
  public surname: string | undefined = prop({ type: String });
  public role?: string | undefined = prop({ type: String });
}
import { Vue } from "vue-class-component";
import { UserInfoProperties } from "./user-info-properties";

export class UserInfo extends Vue.with(UserInfoProperties) {
  public render(): any {
    return (
      <div>
        <p>
          <b>User info:</b>
        </p>
        <p>Name: {this.$props.name}</p>
        <p>Surname: {this.$props.surname}</p>
        <p v-show={this.$props.role}>Role: {this.$props.role}</p>
      </div>
    );
  }
}

Now if you change your Home component class and add the UserInfo component to it, you can see that it is forcing you to pass all required properties to your component. So you can use UserInfo component with role property:

import { Vue } from "vue-class-component";
import { UserInfo } from "./user-info-component";

export class Home extends Vue {
  public render(): any {
    return (
      <div>
        <p>Hello world!!, this is our first vue component with JSX</p>
        <UserInfo name="Hamidreza" surname="Amini" role="developer" />
      </div>
    );
  }
}

Or without role property ( because role is optional in UserInfoProperties class ):

import { Vue } from "vue-class-component";
import { UserInfo } from "./user-info-component";

export class Home extends Vue {
  public render(): any {
    return (
      <div>
        <p>Hello world!!, this is our first vue component with JSX</p>
        <UserInfo name="Hamidreza" surname="Amini" />
      </div>
    );
  }
}

That’s it. Now you can enjoy using vue with typescript and JSX. Please share your comments with me, thanks.