Building a Vue 3 component with Typescript
Lorenzo Millucci
Posted on March 9, 2020
The alpha version of Vue 3 has been available for some time now!
While I’m writing this post the alpha 8 version has just been released.
The new version of Vue will bring with it an avalanche of enhancements and improvements but the most significant changes in the new version will be:
- Composition API: this is a much discussed feature inspired by the React hooks.
- Portals: render certain content outside the current component.
- Fragments: allows multiple root nodes.
- Updated v-model-API: it now accepts multiple models.
- Suspense: is a special component that renders a fallback content instead of your component until a condition is met (mostly for UX stuff).
- TypeScript: Vue now has full TypeScript support.
Since Vue 3 is still under active development some of its components may still have bugs or some API may change but it is already possible to start writing a simple application to start playing with the new features.
Because I’m a big fan of TypeScript in this article I will describe you the steps that I followed to to create a new application with Vue 3 using TypeScript.
But talk is cheap, let’s start setting up a new app 🙂
Setting up the project
The first thing to do is to initialize a new application using the command on the next line:
yarn init
Next, add the dependencies needed by the project:
yarn add vue@3.0.0-alpha.8
yarn add --dev yarn vue-loader@v16.0.0-alpha.3 webpack-cli webpack webpack-dev-server typescript ts-loader @vue/compiler-sfc@v3.0.0-alpha.8
Now you have to define a simple webpack configuration creating the file webpack.config.js
and adding the following code:
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = (env = {}) => ({
mode: env.prod ? 'production' : 'development',
devtool: env.prod ? 'source-map' : 'cheap-module-eval-source-map',
entry: path.resolve(__dirname, './src/main.ts'),
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/'
},
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/],
}
},
]
},
resolve: {
extensions: ['.ts', '.js', '.vue', '.json'],
alias: {
'vue': '@vue/runtime-dom'
}
},
plugins: [
new VueLoaderPlugin(),
],
devServer: {
inline: true,
hot: true,
stats: 'minimal',
contentBase: __dirname,
overlay: true
}
})
So far so good, our setup is coming together, but it won’t compile TypeScript just yet, for that we need to add a tsconfig.json
file with the following rules:
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"declaration": false,
"esModuleInterop": true,
"experimentalDecorators": true,
"module": "es2015",
"moduleResolution": "node",
"noImplicitAny": false,
"noLib": false,
"sourceMap": true,
"strict": true,
"strictPropertyInitialization": false,
"suppressImplicitAnyIndexErrors": true,
"target": "es2015",
"baseUrl": ".",
},
"exclude": [
"./node_modules"
],
"include": [
"./src/**/*.ts",
"./src/**/*.vue",
],
}
After configuring Typescript and Webpack it is time to add a shortcut to start your application adding a new script to the package.json
file:
{
//...
// Dependencies
//...
"scripts": {
"dev": "webpack-dev-server"
}
}
NOTE: to avoid error when you will import *.vue
files you have to add the following shims-vue.d.ts
file in ./src
folder:
declare module "*.vue" {
import { defineComponent } from "vue";
const Component: ReturnType<typeof defineComponent>;
export default Component;
}
To test that the infrastructure built so far is working correctly you will need some things:
- Have a simple
index.html
in the root of the project
<!-- index.html -->
<h1>Hello Vue 3!</h1>
<script src="/dist/main.js"></script>
- Have a
/src
folder - Have
main.ts
file to the project as follows:
// src/main.ts
console.log('Hello world from Typescript!');
- Run the web server with
yarn dev
If everything is working then connecting to http://localhost:8080
you should see the page we have just created.
To recap, at the end of these steps you should have the following architecture:
├── index.html
├── package.json
├── tsconfig.json
├── webpack.config.js
├── src
│ ├── shims-vue.d.ts
│ └── main.ts
Let’s build a component
Now that the environment needed to build the application is finally ready you can start creating your first Vue 3 component.
First of all, add a new file called App.vue
inside the src
folder as follows:
<template>
<h2>This is a Vue 3 component!</h2>
<button @click="increase">Clicked {{ count }} times.</button>
</template>
<script lang="ts">
import {defineComponent, ref} from "vue";
export default defineComponent({
setup() {
const count = ref(0)
const increase = () => {
count.value++
}
return {
count,
increase,
}
}
});
</script>
As you can see, compared to Vue 2 in which to create a new Vue component it was necessary to create a Typescript class and extend Vue using class MyClass extends Vue {}
, now Vue 3 offers a defineComponent()
function.
Inside the defineComponent()
function you can see a setup
function, which takes the props as the first argument. Since in this case the App component will be a top level component, no props will be passed (so I have omitted to pass them on).
Also, as you can see from the code, whatever is returned by the setup()
method, it is then accessible from the template.
Now that the Vue component has been created, you just have to import it into the main.ts
file as follows:
import {createApp} from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
Also in this case you can see how compared to the previous version of Vue it is no longer necessary to initialize the new application with const app = new Vue (....).$Mount('# app')
but with Vue 3 it is possible to use the function createApp()
and the mount()
method to bind the application to a DOM selector.
Finally, the last step is to edit the index.html
file to include the selector specified to Vue in the previous step:
<h1>Hello Vue 3!</h1>
<div id="app"></div>
<script src="/dist/main.js"></script>
At this point, relaunching the application with yarn dev
you can start playing with the new Vue component just created.
Recap
In this post I showed you how to create a very simple component using Vue 3, the composition API and Typescript. Obviously I have scratched just the tip of the iceberg and there are a thousand other features to try in Vue 3 but already with this simple component it is possible to appreciate the new "functional" approach with which it is possible to define the components in the next release of Vue.
PS: All the code is available on GitHub.
Feel free to reach out to me! Blog (in italian) || Twitter || GitHub || LinkedIn
Posted on March 9, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.