Crafting a  Dynamic VueJS Component  Using TSX Files and 
Render Function

Crafting a Dynamic VueJS Component Using TSX Files and Render Function

#VueJS #TSX #RenderFunction #AdvancedPatterns

Just created a step to step tutorial to reproduce the project pattern I have been using these last years ( 2+ years with projects in production currently ).

I'm sure it will bring you some great benefits use VueJS + TSX Files, like:

Type Safety: One of the key benefits of using TSX files in Vue.js is the type safety that it provides. With TypeScript, you can ensure that your components are correctly typed, avoiding errors and improving code quality.

Improved Readability: TSX files can improve the readability of your Vue.js code, making it easier to understand and maintain.

Enhanced Editor Support: Using TSX files in Vue.js can improve the support you get from your code editor, providing enhanced code completion, error highlighting, and more.

Increased Productivity: With its strong typing, improved readability and better editor support, using TSX files in Vue.js can help you write code faster and with fewer errors, ultimately increasing your productivity ?? ??


Disclaimer: This approach can be useful only for Vue Projects version 2+ and 2.6+.


First of all, we need to setup?TSX properly?in your?VueJS?project. To do this, you?must follow these steps:

1- Add Typescript Dependencies (If your project already has typescript, skip this step )

yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/cli-plugin-typescript @vue/eslint-config-typescript typescript        

Ops: I'm assuming you already have a package manager installed. In this example I will use yarn to install Typescript dependencies.

"@typescript-eslint/eslint-plugin" and "@typescript-eslint/parser" are ESLint plugins that add support for TypeScript to the ESLint linter.

"@vue/cli-plugin-typescript" is a plugin for the Vue CLI that adds TypeScript support to Vue.js projects.

"@vue/eslint-config-typescript" is an ESLint config that provides recommended rules for using TypeScript with Vue.js and "typescript" for sure is the programming compiler itself.


2 - Configure your Typescript using tsconig.json file:

N?o foi fornecido texto alternativo para esta imagem

The most important properties for us to set here are:

Include: tells the Typescript compiler what to search for and where to search, in this case any .ts | .tsx | .vue files inside src or test folder.

jsx: preserve: this property specify how Typescript should handle JSX syntax, the "preserve" option ensures that JSX syntax is preserved during compilation, which means that will be outputted as-is in the compiled Javascript code.

Ops: Don't forgot to set Include and jsx properties even if your project already has Typescript


3 - Providing .d.ts files for your TS compile

Create and save these files on your project root:

N?o foi fornecido texto alternativo para esta imagem
N?o foi fornecido texto alternativo para esta imagem

In TypeScript, .d.ts files are definition files that describe the shape of a JavaScript module or library's API, they are used to provide type information for third-party JavaScript libraries or modules that don't have TypeScript definitions included.

By including these .d.ts files in your TypeScript project, you will get the benefits of TypeScript's type checking for Vue components written in .TSX files, in addiction to keep our compiler aware that we are going to write JSX inside Vue components.


4 - Now, let's configure your babel !

The most important setup dependency you might need is @Vue/babel-preset-jsx

Created by the Vuejs Core Team, it's a babel transpiler that allows you to create VueJS components using render functions and to write your VueJS components using .TSX or .JSX files.

Add these follow dev dependencies:

yarn add -D @babel/core @babel/preset-env @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props        

Then, create your .babelrc in your project root, and set the preset property with "@vue/babel-preset-jsx".

N?o foi fornecido texto alternativo para esta imagem

It will allow you to use JSX within Vue components.

Now you are ready to create something beautiful like this:

// MyComp.tsx 

export default {
? render() {
? ? return <p>hello</p>
? }
}        

or even better like this:

// MyComp.tsx 

export default {
  ?render() {
    const inputAttrs = {
      type: 'email',
      placeholder: 'Enter your email'
    }
  
       return <input {...{ attrs: inputAttrs }} />
    }
  }        

now you have 100% Vue functional components also:

export default ({ props }) => <p>hello { props.message }</p>        

5 - To proceed, we'll need to develop a wrapper class for our Vue Components. To do so, we should create a new folder in the project root directory and name it "config". Then, we can add a file to this folder called "vue-components.ts".

N?o foi fornecido texto alternativo para esta imagem


The idea behind this class is to act as a wrapper providing type safety for all your components props.

By extending the Vue class and defining a generic $props property with the P type, we can ensure that our components receive the correct props and avoid runtime errors.


6 - Let's code

N?o foi fornecido texto alternativo para esta imagem


Let's bring this idea to the real world, I will show you how to easily?customize?and?manage a?typography component throughout your application,?ensuring consistency and a polished?look by using TSX file to create and render your component.

First of all, I would recommend using the Vue Facing Decorator library to enhance your developer experience. It provides a set of decorators that are useful in creating reactive properties and methods for Vue components, allowing you to quickly bootstrap your components using TypeScript.

Check out the Docs ( Portuguese translation made by me ?????? )


Alright, without further ado, let's checkout our Typography component structure :

Typography/?

	├── prop-accessor.ts? 

	└──?index.tsx         

Let's start by the?Typography/props-accessor.ts:

N?o foi fornecido texto alternativo para esta imagem

A module that exports an object with?different typography keys, representing?different font sizes and?styles, each?with their own set of CSS properties such?as?font size,?line height, and?fontWeight.?

We are?going to?take advantage of render?function flexibility with this afterwards.

Here is our Typography/index.tsx:

N?o foi fornecido texto alternativo para esta imagem


Here, we are taking advantage of our VueComponent class wrapper ( previous step ), to define an interface for our Typography component, ensure type-safety and for sure for intellisense proposes.

Note: the '?' operator in the TypographyProps interface creates optional parameters, so if you don't pass anything to those parameters, TypeScript won't throw any error. Otherwise, it will throw ( see image below, props 'as' is required ).


Our Typography.tsx Component now has:

N?o foi fornecido texto alternativo para esta imagem
Type-safety


N?o foi fornecido texto alternativo para esta imagem
Intellisense


N?o foi fornecido texto alternativo para esta imagem
Intellisense on props + props values


8 - Bonus: Creating a flexible Input Component

We can create a truly flexible Input component by spreading $attrs and $listeners objects into "attrs" and "on" properties respectively, this can ensure that any non-props attributes or listeners passed to the parent component are passed down to the rendered HTML element.

e.g:

// Input.tsx

import { Component } from 'vue-facing-decorator'
import { VueComponent } from '@/config/vue-component.ts'
 
@Component({})
export default class Input extends VueComponent {
 
  render(h) {
    return h( 
      'input', 
      {
        attrs: { ...this.$attrs },
        on: { ...this.$listeners }
      }
    ) 
  }
}        

You can create any input using this component, without needed to create props for any Html Input Attributes for example. ????

Or even better, you can take advantage of some UI Library like ChakraUI and extend a pre-build Input Component.

// Input.tsx

import { Component } from 'vue-facing-decorator'
import { VueComponent } from '@/config/vue-component.ts'
import { CInput } from '@chakra-ui/vue' 

@Component({})
export default class Input extends VueComponent {
 
  render(h) {
    return h( 
      CInput, <-- here is where you extend your pre-made component 
      {
        attrs: { ...this.$attrs },
        on: { ...this.$listeners }
      }
    ) 
  }
}        

Now your Input Component inherit all Chakra UI Style Props and Chakra Input Props in less than 20 lines. ??????

That's all folks !

N?o foi fornecido texto alternativo para esta imagem
https://github.com/BrendonHenrique
Danilo Cardoso

Full Stack Developer @ Ethosx - Vue | React | Node | Typescript | PHP | JavaScript | Kanban | UX/UI | APIs

9 个月

An update using more current resources like Vite, etc. would be interesting. How would you approach style in this case? In short, the step by step was incredible

回复

Amazing Brendon ????????????

要查看或添加评论,请登录

社区洞察

其他会员也浏览了