Pular para o conteúdo

Programando Soluções

O que são e como usar props no Vue 3

  • por
props

Introdução

As props são utilizadas para passar dados de um componente pai para um componente filho.

Com isso um componente pode ser mais flexível e reutilizável, pois você poderá usá-lo em mais de um local do sistema, e os valores que forem diferentes você pode passar para ele utilizar.

Essa funcionalidade já existia no Vue 2, então para você que já mexe com Vue não é novidade, e a forma de utilizar no Vue 3 é bem parecida.

Como usar

Para mostrar o funcionamento, vou usar dois componentes, o App.vue e vou criar um componente Artigo.vue.

No caso o componente App será o componente pai, e enviará dados ao componente Artigo.vue.

O componente de Artigo, simula a exibição de um post de blog, e como todo post, precisa ter um título, então o App.vue irá fornecer essa informação para ele. Obs: poderia fazer isso de outras formas, porém dessa forma da para ilustrar a passagem de dados.

Para um componente declarar que pode receber uma prop, tem algumas formas de fazer.

A mais simples é definir na parte de script a chave props, com um array com todas as propriedades que pode receber.

Ao definir dessa forma é possível utilizar o valor recebido dentro do template, como uma variável do próprio componente.

O componente Artigo.vue ficará dessa forma:

<template>
  <h2>{{titulo}} </h2> <!-- exibe o valor recebido de "titulo" na tela -->
</template>

<script>
export default {
    props: ['titulo']; //indica que esse componente pode receber a propriedade "titulo"
}
</script>

E o componente App.vue

<template>
  <Artigo titulo="Um titulo para o artigo" /> <!-- O valor passado para o outro componente -->
</template>

<script>
import Artigo from './components/Artigo.vue'
export default {
  name: 'App',
  components: {
    Artigo
  }
}
</script>

Passando valor dinâmico

No primeiro exemplo, no App.vue foi passado um valor fixo para o titulo do Artigo.

Porém imagine que esse titulo seja recebido por alguma API, seria necessário passar o valor para o componente de Artigo conforme o valor for recebido e não um título fixo.

Para isso o valor precisaria ser armazenado em uma variável dentro do App.vue, e na chamada do componente Artigo, passar essa variável na prop titulo.

Como você já viu o artigo que fiz falando sobre o setup, essa variável precisa ser retornada por ele para ser utilizado no template.

E o código do App.vue fica dessa forma:

<template>
  <!-- quando o valor da prop é uma variável, é necessário colocar o dois pontos antes para que a prop interprete esse valor como variável -->
  <Artigo :titulo="titulo" />
</template>

<script>
import Artigo from './components/Artigo.vue'

export default {
  name: 'App',
  components: {
    Artigo
  },
  setup () {
    let titulo = "Titulo do artigo"; //simulação de um título recebido dinamicamente

    return {
      titulo
    } //retorno da variável titulo para usar no template
  }
}
</script>

Definir tipo de dados

O Artigo vai receber o título, mas, e se um outro programador for usar esse componente e no local do título passar um número em vez de um texto.

Isso irá funcionar, porém não da maneira como deveria, porque um título válido deveria ser uma string.

Para isso é possível melhorar a declaração da prop que o componente Artigo.vue espera receber, indicando que o título precisa ser string.

Em vez de indicar os valores a receber como um array, cada prop será um objeto que pode receber algumas configurações, essa primeira será a configuração type.

É possível passar os tipos String, Number, Boolean, Array, Object, Function e Promise.

A prop título fica dessa forma:

<script>
export default {
    props: {
        titulo: {
            type: String
        }
    }
}
</script>

E dessa forma, caso o outro programador passe um número em vez de string, irá mostrar um warning no console, indicando que o parâmetro enviado é diferente do tipo esperado.

E possível também esperar mais de um tipo, vamos supor que por algum motivo o título poderia ser um número, daria para esperar somente string ou número dessa forma:

<script>
export default {
    props: {
        titulo: {
            type: [String, Number]
        }
    }
}
</script>

E se um Boolean fosse passado, também mostraria o warning.

Passar um número ou booleano

Para passar um número ou booleano em uma prop tem uma particularidade.

É necessário passar esse valor da mesma forma que uma variável, para que esse valor seja interpretado da maneira correta.

Para esse exemplo, no Artigo.vue, vou declarar que ele pode receber uma outra prop chamada quantidadeCaracteres, que seria a quantidade de caracteres de um artigo.

<script>
export default {
    props: {
        titulo: {
            type: String
        },
        quantidadeCaracteres: {
            type: Number
        }
    }
}
</script>

Agora no App.vue, vou passar o valor que é um número para o Artigo.vue

<template>
  <Artigo :titulo="titulo" :quantidadeCaracteres="600" />
</template>

No caso o 600 será interpretado como número, porque foi indicado o dois pontos antes do quantidadeCaracteres.

Caso não tenha esse dois pontos, irá indicar o warning no console, porque o Vue entenderá que o valor passado foi uma string.

No caso de booleanos o problema pode ser um pouco maior, porque normalmente eles são utilizados para ajudar em alguma lógica, e o algoritmo pode não funcionar como esperado, porque o valor recebido será uma string.

Valor padrão

A prop quantidadeCaracteres não será obrigatória, porém gostaria que tivesse um valor padrão para ela, caso não fosse passado nenhum valor na chamada do componente Artigo.

Como agora a prop tem um objeto de configurações, uma das opções que é possível passar é a opção default.

Com essa opção, caso o valor não seja passado por quem chama o componente, será assumido o valor declarado no default.

<template>
  <h2>{{titulo}} - {{ quantidadeCaracteres }}</h2>
</template>

<script>
export default {
    props: {
        titulo: {
            type: String
        },
        quantidadeCaracteres: {
            type: Number,
            default: 0 // caso não receba nenhum valor, essa prop assume o valor 0 como padrão
        }
    }
}
</script>

Prop obrigatória

A quantidade de caracteres talvez não seja um valor obrigatório, não tem tanta relevância, porém o título do artigo tem, e precisa ser passado.

Porém atualmente caso não seja passado, não será indicado de nenhuma forma que é obrigatório para o programador que esteja usando o componente.

Para fazer com que apareça o warning no console, é possível indicar a chave required na configuração da prop, e isso pode facilitar para quem vai usar esse componente, dessa forma:

<script>
export default {
    props: {
        titulo: {
            type: String,
            required: true //indica que a prop é obrigatória
        },
        quantidadeCaracteres: {
            type: Number,
            default: 0
        }
    }
}
</script>

Fluxo de dados unidirecional

Todas as props tem ligação unidirecional, e isso significa que quando o valor da propriedade é alterado no componente pai, reflete a alteração para o componente filho.

Porém se a prop for atualizada no componente filho, as alterações não refletem no componente pai.

E isso ajuda você a compreender o fluxo de dados na aplicação, e ajuda também com que por acidente o valor não seja trocado onde não pode.

Porém caso você queira atualizar um dado recebido como prop, o ideal é declarar uma variável interna no componente, que receba o valor da prop inicialmente, e dessa forma você pode alterar somente nesse componente.

Para um exemplo vou manipular o valor do título, fazendo um tratamento para que ele fique todo em maiúsculo:

<template>
  <h2>{{novoTitulo}} - {{ quantidadeCaracteres }}</h2>
</template>
<script>
import { reactive } from '@vue/reactivity';
export default {
    props: {
        titulo: {
            type: String,
            required: true
        },
        quantidadeCaracteres: {
            type: Number,
            default: 0
        }
    },
    setup (props) {
        const novoTitulo = reactive(props.titulo.toUpperCase());
        return {
            novoTitulo
        }
    }
}
</script>

Nesse caso a variável novoTitulo, vai ter como valor inicial o valor da prop recebida, e já aplica o tratamento de deixar todo o título em maiúsculo.

A variável interna é retornada pelo setup e pode ser utilizada normalmente no template.

Conclusão

Este recurso é muito utilizado no dia a dia, possibilita que um componente seja mais personalizável e reutilizável.

Há algumas regras para se atentar no uso porém no geral é bem traquilo.

Como dica extra, sempre declare as props em formato de objeto e passando as opções de configuração, vai ficar mais fácil para ler o código e dar manutenção.

Código Fonte

O código fonte dos exemplos está no meu CodeSandbox.

Para ver outros canais onde o posto conteúdo sobre VueJS, veja os Links do Programando Soluções.

Referências

https://v3.vuejs.org/guide/component-props.html

Este conteúdo te ajudou de alguma forma?

Marcações:
Usamos cookies para lhe proporcionar a melhor experiência possível no nosso site. Ao continuar a usar este site, você concorda com o uso de cookies.
Ok