(How) Should I use access modifiers (public, private etc.) in Vue.js components (TypeScript)?

Viewed 1505

I have a Vue.js v2.6 project with TypeScript v.4.3 "under the hood".
My problem: I cannot find any documentation that clears up, if it makes sense to use access modifiers in Vue components and how to use them correctly.
I searched through articles, Vue.js docs, and StackOverflow, without any findings. (The Vue.js docs ignore their existence completely!)

This is how I am currently using access modifiers in my Vue components:

Template part of myComponent.vue:

<template>
  <div>
    <!-- accessing some of the fields of the class here e.g. the getter -->
  </div>
</template>

Script part of myComponent.vue:

<script lang="ts">
  import { Vue, Component, Prop, Emit } from "vue-property-decorator";

  @Component()
  export default class MyComponent extends Vue {
    @Prop() public readonly myPropertyVariable!: boolean;

    public myVariable!: string; // accessed in template

    private myInternalVariable!: boolean; // not accessed in template

    public get myGetterVariable(): string {
       // obviously accessed in template (getter)
    }

    @Emit()
    public change(): void {}

    @Action
    public doAction(): void {}

    public mounted(): void {}

    public myMethod(): boolean {
      // accessed in template
    }

    private myInternalMethod(): boolean {
      // not accessed in template
    }
  }
</script>

I hope, this is not an opinion-based question. I am assuming there a facts that confirm the meaningfulness of access modifiers in Vue components. I have a strong, possibly irrational resistance to omit them all.

Btw: I am coding in Rider, the access modifiers might be useful for IDE code analysis.

4 Answers

If it works like Angular, a public modifier as you commented in your code, will make sure that your template can call those public functions.

Perhaps as the other fellow devs say, in the use case of @refs. (Although if you need them, there's is a good chance you are spaghetti coding)

Marking a method private is just a way to say "this doesn't belong to the template".

In these "frontend scenarios" where classes are kind of forced, the use of accessors just increases readability (and confusion :D)

This question wasn't answered in that other thread, mostly because it's common sense and style, and my 2 cents are, use private when you don't want to target the template, just to increase your code readability.

As a side note, I've been working with vue and typescript for 3 years now, and the one thing I can tell you is, I always found vue class components bloatware, especially in vue3. Vue2 and 3 support brilliantly typescript without any need for class components.

I found in my projects that the public/private access modifiers are only useful when your components are referenced from other components (e.g. using the @Ref property decorator)

TypeScript's public/private access modifiers do not affect the transpiled output and thus have no effect within Vue's ecosystem. You can still use them but they will only help during development by providing property access errors.

See: TypeScript Support for Vue.js

This extension is specific to VSCode, but seems to align with what you're looking for: https://github.com/prograhammer/vscode-tslint-vue

Public/Private modifiers are used when you want a logical separation of what can and can't access something. For instance, in Object Oriented Programming, we declare the attributes of an object private, because you never directly access those attributes. Instead you perform an action to modify or access those attributes. This is just an old programming paradigm.

The example I give my students is to consider for instance, a real world object. Take for instance a Pencil. We define its attributes and say okay, the pencil has a length, a sharpness, and a color.

Each of these attributes, length, sharpness, and color, would all be prefaced with the modifier private because we would never be able to magically change these attributes. If we made them public attributes, we could just do:

pencil.color = "blue";

And suddenly our pencil is blue. But we have no idea how we got here, or why. It's spontaneous pencil color changing. We have ignored the process or function or method required to get to this point.

So instead, at a very basic level, we get or set the color of the pencil. This is another old object oriented paradigm, read: getters and setters (which are a whole different discussion). The functions would then be declared public because they are representative of the action that the object can perform or have performed on it. That way if you wanted to paint all of your pencils blue, somewhere else in your code, you could do this:

List<Pencil> my_pencils = pencilFairy.producePencils();
    for(Pencil p : my_pencils){
        p.paint("Blue");    
    }

And this way, for each pencil, which we will call p, in our pencils (that we acquired from the pencilFairy's recent production) we want to paint the pencil blue. And within the Pencil class, the logic required to define how painting a pencil, would then be defined.

TLDR; You use private to define something's attributes because things outside of that object should not be able to mystically and magically modify those attributes, and you use public to define the functions or methods that can be performed on/by/to that object, and those actions can modify those attributes or return some other info based on those attributes, etc.

EDIT: Rereading the question, I'm sure you know most of this already. Just providing my hot take on how I decide when and where something should be public/private.

Related