{
    "componentChunkName": "component---src-templates-post-post-tsx",
    "path": "/blog/using-vue-with-typescript-and-jsx",
    "result": {"data":{"post":{"id":"cG9zdDo0Ng==","title":"Using Vue with Typescript and JSX","slug":"using-vue-with-typescript-and-jsx","uri":"/using-vue-with-typescript-and-jsx/","date":"December 31, 2020 - 20:13","content":"\n<h2 class=\"wp-block-heading\">Why Typescript and JSX?</h2>\n\n\n\n<p>Hi everyone,<br>I like using <strong><a href=\"/blog/category/typescript/\" target=\"_blank\" rel=\"noreferrer noopener\">typescript</a></strong> and <strong><a href=\"/blog/category/front-end/jsx/\" target=\"_blank\" rel=\"noreferrer noopener\">JSX</a></strong> in front-end development, that&#8217;s why I was attracted to <strong>React</strong>. But you can use class component, with typescript and JSX in developing your front-end with <strong><a href=\"/blog/category/front-end/vue/\" target=\"_blank\" rel=\"noreferrer noopener\">Vue</a></strong>. In this post I want to show you how to do it.</p>\n\n\n\n<p>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.</p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Start</h2>\n\n\n\n<h3 class=\"wp-block-heading\">Installing the requirements for Vue, JSX and Typescript</h3>\n\n\n\n<p>First of all, you need to install the vue 3+, vue-class-component 8+, babel 7+, vue cli and typescript:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>npm i vue@^3.0.0\n##\nnpm i vue-class-component@^8.0.0-rc\n##\nnpm i @babel/core\n##\nnpm i @vue/cli\n##\nnpm i typescript</code></pre></div>\n\n\n\n<p>After that you should install <strong>webpack</strong>, <strong>webpack-cli</strong>, <strong>webpack-dev-server</strong> ( if you don&#8217;t have any specific server ), <strong>babel-loader</strong> and <strong>ts-loader</strong>:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>npm i webpack\n##\nnpm i webpack-cli@3.3.11\n##\nnpm i webpack-dev-server\n##\nnpm i babel-loader\n##\nnpm i ts-loader</code></pre></div>\n\n\n\n<p>For using <strong>JSX</strong> in your components, you need to install the following packages:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>npm i @vue/babel-preset-app\n##\nnpm i @vue/babel-plugin-jsx</code></pre></div>\n\n\n\n<h3 class=\"wp-block-heading\">Configurations</h3>\n\n\n\n<p>And then configure your <strong>.babelrc</strong> file like this:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-json\" data-file=\".babelrc\" data-lang=\"JSON\"><code>{\n  &quot;presets&quot;: [&quot;@vue/babel-preset-app&quot;],\n  &quot;plugins&quot;: [&quot;@vue/babel-plugin-jsx&quot;]\n}</code></pre></div>\n\n\n\n<p>Then, create the <strong>webpack.config.js</strong> file in your root and use the following config:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-js\" data-file=\"webpack.config.js\" data-lang=\"JavaScript\"><code>const { join } = require(&#39;path&#39;);\n\nmodule.exports = {\n  mode: &#39;development&#39;,\n  target: &#39;web&#39;,\n  entry: join(__dirname, &#39;./app/index.tsx&#39;),\n  output: {\n    filename: &#39;bundle.js&#39;,\n    path: join(__dirname, &#39;dist&#39;)\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.(ts|tsx)/,\n        exclude: /node_modules/,\n        use: [{ loader: &#39;babel-loader&#39; }, { loader: &#39;ts-loader&#39; }]\n      }\n    ]\n  },\n  watch: true,\n  resolve: {\n    extensions: [&#39;.ts&#39;, &#39;.tsx&#39;, &#39;.js&#39;, &#39;.jsx&#39;, &#39;.styl&#39;]\n  },\n  devServer: {\n    contentBase: join(__dirname, &#39;./app&#39;),\n    compress: true,\n    port: 9000,\n    publicPath: &#39;/dist/&#39;\n  }\n};</code></pre></div>\n\n\n\n<p>Also you should configure your tsconfig.json file as below:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-json\" data-file=\"tsconfig.json\" data-lang=\"JSON\"><code>{\n  &quot;compileOnSave&quot;: true,\n  &quot;compilerOptions&quot;: {\n    &quot;experimentalDecorators&quot;: true,\n    &quot;target&quot;: &quot;esnext&quot;,\n    &quot;strict&quot;: true,\n    &quot;module&quot;: &quot;ESNext&quot;,\n    &quot;moduleResolution&quot;: &quot;node&quot;,\n    &quot;jsx&quot;: &quot;preserve&quot;,\n    &quot;strictPropertyInitialization&quot;: false\n  },\n  &quot;exclude&quot;: [&quot;node_modules&quot;]\n}</code></pre></div>\n\n\n\n<h3 class=\"wp-block-heading\">Start creating vue components with JSX and typescript</h3>\n\n\n\n<p>Then create a folder called <strong>app</strong> ( or any other name that you like, but you should remember to use the correct direction for your <strong>entry</strong> in <strong>webpack.config.js</strong> file) and create your first component in this folder like this:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-ts\" data-file=\"/app/home-component.tsx\" data-lang=\"TypeScript\"><code>import { Vue } from &quot;vue-class-component&quot;;\n\nexport class Home extends Vue {\n  public render(): any {\n    return &lt;p&gt;Hello world!!, this is our first vue component with JSX&lt;/p&gt;;\n  }\n}</code></pre></div>\n\n\n\n<p>Now we need an HTML file that I called it index.html and put it in <strong>app</strong> folder: ( you can use a different name or put it in a different folder, but remember to change the <strong>devSever</strong> configuration of your <strong>webpack.config.js</strong> file)</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-html\" data-file=\"/app/index.html\" data-lang=\"HTML\"><code>&lt;!DOCTYPE html&gt;\n&lt;html lang=&quot;en&quot;&gt;\n  &lt;head&gt;\n    &lt;meta charset=&quot;UTF-8&quot; /&gt;\n    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;\n    &lt;title&gt;Document&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;\n    &lt;script src=&quot;/dist/bundle.js&quot;&gt;&lt;/script&gt;\n  &lt;/body&gt;\n&lt;/html&gt;</code></pre></div>\n\n\n\n<p>Now you just need an entry point which is a file in <strong>app</strong> folder, called index.tsx. You should pass your main component to <strong>createApp</strong> function and then mount it to any specific element of your DOM. Here we are mounting it to an element that its ID is <strong>&#8220;root&#8221;</strong>:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-ts\" data-file=\"/app/index.tsx\" data-lang=\"TypeScript\"><code>import { createApp } from &quot;vue&quot;;\nimport { Home } from &quot;./home-component&quot;;\n\ncreateApp(&lt;Home /&gt;).mount(&quot;#root&quot;);</code></pre></div>\n\n\n\n<p>Then you can add the start script to your package.json as the following:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-json\" data-file=\"package.json\" data-lang=\"JSON\"><code>{\n  ...\n  &quot;scripts&quot;: {\n    &quot;start&quot;: &quot;webpack-dev-server&quot;\n  },\n  ...\n}\n</code></pre></div>\n\n\n\n<p>After that use the following command:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>npm start</code></pre></div>\n\n\n\n<p>For using properties in your component, you need to create a class and use it in your component like this:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-ts\" data-file=\"/app/user-info-properties.tsx\" data-lang=\"TypeScript\"><code>import { prop } from &quot;vue-class-component&quot;;\n\nexport class UserInfoProperties {\n  public name: string | undefined = prop({ type: String });\n  public surname: string | undefined = prop({ type: String });\n  public role?: string | undefined = prop({ type: String });\n}</code></pre></div>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-ts\" data-file=\"/app/user-info-component.tsx\" data-lang=\"TypeScript\"><code>import { Vue } from &quot;vue-class-component&quot;;\nimport { UserInfoProperties } from &quot;./user-info-properties&quot;;\n\nexport class UserInfo extends Vue.with(UserInfoProperties) {\n  public render(): any {\n    return (\n      &lt;div&gt;\n        &lt;p&gt;\n          &lt;b&gt;User info:&lt;/b&gt;\n        &lt;/p&gt;\n        &lt;p&gt;Name: {this.$props.name}&lt;/p&gt;\n        &lt;p&gt;Surname: {this.$props.surname}&lt;/p&gt;\n        &lt;p v-show={this.$props.role}&gt;Role: {this.$props.role}&lt;/p&gt;\n      &lt;/div&gt;\n    );\n  }\n}</code></pre></div>\n\n\n\n<p>Now if you change your <strong>Home</strong> component class and add the <strong>UserInfo</strong> component to it, you can see that it is forcing you to pass all required properties to your component. So you can use <strong>UserInfo</strong> component with <strong>role</strong> property:</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-ts\" data-file=\"/app/home-component.tsx\" data-lang=\"TypeScript\"><code>import { Vue } from &quot;vue-class-component&quot;;\nimport { UserInfo } from &quot;./user-info-component&quot;;\n\nexport class Home extends Vue {\n  public render(): any {\n    return (\n      &lt;div&gt;\n        &lt;p&gt;Hello world!!, this is our first vue component with JSX&lt;/p&gt;\n        &lt;UserInfo name=&quot;Hamidreza&quot; surname=&quot;Amini&quot; role=&quot;developer&quot; /&gt;\n      &lt;/div&gt;\n    );\n  }\n}</code></pre></div>\n\n\n\n<p>Or without <strong>role</strong> property ( because <strong>role</strong> is <strong>optional</strong> in <strong>UserInfoProperties</strong> class ):</p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-ts\" data-file=\"/app/home-component.tsx\" data-lang=\"TypeScript\"><code>import { Vue } from &quot;vue-class-component&quot;;\nimport { UserInfo } from &quot;./user-info-component&quot;;\n\nexport class Home extends Vue {\n  public render(): any {\n    return (\n      &lt;div&gt;\n        &lt;p&gt;Hello world!!, this is our first vue component with JSX&lt;/p&gt;\n        &lt;UserInfo name=&quot;Hamidreza&quot; surname=&quot;Amini&quot; /&gt;\n      &lt;/div&gt;\n    );\n  }\n}</code></pre></div>\n\n\n\n<p>That&#8217;s it. Now you can enjoy using <strong>vue</strong> with <strong>typescript</strong> and <strong>JSX</strong>. Please share your <strong>comments</strong> with me, thanks.</p>\n","author":{"node":{"name":"hamidreza","avatar":{"url":"https://secure.gravatar.com/avatar/c4ef37782a933163dcb8e61b6a02dbbe?s=96&d=mm&r=g","width":96,"height":96}}},"featuredImage":{"node":{"sourceUrl":"https://hramini-back.ir/wp-content/uploads/2020/12/vuejs-jsx-typescript.png","altText":"","srcSet":"https://hramini-back.ir/wp-content/uploads/2020/12/vuejs-jsx-typescript-300x158.png 300w, https://hramini-back.ir/wp-content/uploads/2020/12/vuejs-jsx-typescript-1024x538.png 1024w, https://hramini-back.ir/wp-content/uploads/2020/12/vuejs-jsx-typescript-768x403.png 768w, https://hramini-back.ir/wp-content/uploads/2020/12/vuejs-jsx-typescript.png 1440w","sizes":"(max-width: 300px) 100vw, 300px","mediaDetails":{"height":756,"width":1440}}},"categories":{"nodes":[{"slug":"jsx","uri":"/category/front-end/jsx/","name":"JSX"},{"slug":"typescript","uri":"/category/typescript/","name":"Typescript"},{"slug":"vue","uri":"/category/front-end/vue/","name":"Vue"}]}}},"pageContext":{"postId":"cG9zdDo0Ng==","categoryId":"dGVybToxMQ=="}},
    "staticQueryHashes": []}