# Propriedades

Esta página assume que você já leu o Básico sobre Componentes. Leia lá primeiro caso seja novo com componentes.

Aprenda como props de componentes funcionam com uma aula gratuita na Vue School

# Tipos de Propriedades

Até agora, nós apenas vimos propriedades listadas como um Array de Strings:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
1

Mas normalmente, você vai querer que cada propriedade seja de um tipo específico de valor. Nestes casos, você pode listar as propriedades como um objeto cujas chaves e valores contém o nome e o tipo da propriedade, respectivamente:

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // ou qualquer outro construtor
}
1
2
3
4
5
6
7
8
9

Fazer isso não apenas documenta seu componente, mas também mostra um aviso aos usuários no console JavaScript do navegador se eles passarem o tipo errado. Você irá aprender muito mais sobre checagem de tipos e outras validações de propriedades mais abaixo nesta página.

# Passando Propriedades Estáticas ou Dinâmicas

Até agora, você viu propriedades passando um valor estático, como por exemplo:

<blog-post title="Minha jornada com Vue"></blog-post>
1

Você também viu propriedades atribuídas dinamicamente com v-bind ou sua abreviação, o caractere :, como em:

<!-- Dinamicamente atribui o valor de uma variável -->
<blog-post :title="post.title"></blog-post>

<!-- Dinamicamente atribui o valor de uma expressão complexa -->
<blog-post :title="post.title + ' by ' + post.author.name"><blog-post>
1
2
3
4
5

Em ambos os exemplos acima nós passamos valores de String, mas qualquer tipo de valor pode ser passado para uma propriedade.

# Passando um Número

<!-- Apesar de `42` ser estático, precisamos do v-bind para dizer -->
<!-- ao Vue que esta é uma expressão JavaScript e não uma String. -->
<blog-post :likes="42"></blog-post>

<!-- Dinamicamente atribui o valor de uma variável. -->
<blog-post :likes="post.likes"></blog-post>
1
2
3
4
5
6

# Passando um Boolean

<!-- Incluir a propriedade, sem valor nenhum, implica em `true`. -->
<!-- Se você não definir o tipo de is-published como Boolean em props, será uma string vazia em vez de um valor "true". -->
<blog-post is-published></blog-post>

<!-- Apesar de `false` ser estático, precisamos do v-bind para dizer -->
<!-- ao Vue que esta é uma expressão JavaScript e não uma String.    -->
<blog-post :is-published="false"></blog-post>

<!-- Dinamicamente atribui o valor de uma variável. -->
<blog-post :is-published="post.isPublished"></blog-post>
1
2
3
4
5
6
7
8
9
10

# Passando um Array

<!-- Apesar de o Array ser estático, precisamos do v-bind para dizer -->
<!-- ao Vue que esta é uma expressão JavaScript e não uma String.    -->
<blog-post :comment-ids="[234, 266, 273]"></blog-post>

<!-- Dinamicamente atribui o valor de uma variável. -->
<blog-post :comment-ids="post.commentIds"></blog-post>
1
2
3
4
5
6

# Passando um Objeto

<!-- Apesar de o objeto ser estático, precisamos do v-bind para dizer -->
<!-- ao Vue que esta é uma expressão JavaScript e não uma String.     -->
<blog-post
  :author="{
    name: 'Veronica',
    company: 'Veridian Dynamics'
  }"
></blog-post>

<!-- Dinamicamente atribui o valor de uma variável. -->
<blog-post :author="post.author"></blog-post>
1
2
3
4
5
6
7
8
9
10
11

# Passando as Propriedades de um Objeto

Se você deseja passar todas as propriedades de um objeto como propriedades, você pode utilizar o v-bind sem argumentos (v-bind no lugar de :nome-da-propriedade). Por exemplo, dado um objeto post:

post: {
  id: 1,
  title: 'Minha Jornada com Vue'
}
1
2
3
4

O seguinte template:

<blog-post v-bind="post"></blog-post>
1

Será equivalente a:

<blog-post v-bind:id="post.id" v-bind:title="post.title"></blog-post>
1

# Fluxo de Dados Unidirecional

Todas as propriedades formam um vínculo unidirecional para baixo entre a propriedade do filho e a do pai: quando a propriedade do pai é atualizada, ela vai fluir para baixo até o filho, mas não do filho para o pai. Isso evita que componentes filhos acidentalmente alterem o estado do pai, o que pode tornar o fluxo de dados da sua aplicação mais difícil de entender.

Além disso, toda vez que o componente pai é atualizado, todas as propriedades no componente filho serão atualizadas com o valor mais recente. Isso significa que você não deve tentar alterar uma propriedade dentro do componente filho. Se você tentar, o Vue vai te avisar no console.

Existem dois casos mais comuns onde é tentador alterar uma propriedade:

  1. A propriedade é usada para passar um valor inicial; após isso, o componente filho quer usá-la como uma propriedade de dado local. Neste caso, é melhor definir uma propriedade de dados local que usa a propriedade recebida como seu valor inicial:
props: ['initialCounter'],
data() {
  return {
    counter: this.initialCounter
  }
}
1
2
3
4
5
6
  1. A propriedade é passada como um valor puro que precisa ser transformado. Neste caso, é melhor definir uma propriedade computada usando o valor da propriedade recebida:
props: ['size'],
computed: {
  normalizedSize() {
    return this.size.trim().toLowerCase()
  }
}
1
2
3
4
5
6

Aviso

Observe que objetos e arrays em JavaScript são passados por referência, então se a propriedade for um array ou objeto, alterar o objeto ou array em si dentro do componente filho vai afetar o estado pai e o Vue não pode avisá-lo sobre isso. Como regra geral, você deve evitar alterar qualquer prop, incluindo objetos e arrays, pois isso ignora a vinculação de dados unidirecional e pode causar resultados indesejados.

# Validação de Propriedades

Componentes podem especificar requerimentos para suas propriedades, tais como os tipos que você já viu. Se um requerimento não for satisfeito, o Vue irá avisá-lo no console JavaScript do navegador. Isso é especialmente útil ao desenvolver um componente que será utilizado por outras pessoas.

Para especificar as validações de propriedade, você pode fornecer um objeto com os requerimentos de validação ao valor de props, ao invés de um Array de Strings. Por exemplo:

app.component('my-component', {
  props: {
    // Checagem básica de tipo (valores `null` e `undefined` passam qualquer validação de tipo)
    propA: Number,
    // Múltiplos tipos possíveis
    propB: [String, Number],
    // String obrigatória
    propC: {
      type: String,
      required: true
    },
    // Number com valor padrão
    propD: {
      type: Number,
      default: 100
    },
    // Object com valor padrão
    propE: {
      type: Object,
      // Object ou Array padrões devem ser retornados
      // de uma função construtora
      default() {
        return { message: 'hello' }
      }
    },
    // Função validadora customizada
    propF: {
      validator(value) {
        // O valor passado deve bater com alguma destas Strings
        return ['success', 'warning', 'danger'].includes(value)
      }
    },
    // Função com valor padrão
    propG: {
      type: Function,
      // Diferente de um Object ou Array padrão, isto não é uma função construtora - é uma função para servir de valor padrão
      default() {
        return 'Função padrão'
      }
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

Quando a validação de uma propriedade falha, o Vue irá produzir um aviso no console (se estiver usando a versão de desenvolvimento).

Observação

Observe que as propriedades são validadas antes de a instância do componente ser criada, então as propriedades de instância (como data, computed, etc) não estarão disponíveis dentro das funções default ou validator.

# Checagem de Tipos

O type (tipo) pode ser um dos seguintes construtores nativos:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

Além disso, type também pode ser uma função construtora customizada e a asserção será feita com uma checagem através de instanceof. Por exemplo, dada a seguinte função construtora já existente:

function Person(firstName, lastName) {
  this.firstName = firstName
  this.lastName = lastName
}
1
2
3
4

Você poderia usar:

app.component('blog-post', {
  props: {
    author: Person
  }
})
1
2
3
4
5

para validar que o valor da propriedade author foi criada utilizando new Person.

# Case de Propriedades (camelCase vs kebab-case)

Nomes de atributos HTML são case-insensitive, logo navegadores irão interpretar quaisquer caracteres maiúsculos como minúsculas. Isso significa que quando você está usando templates dentro do DOM, nomes de propriedades em camelCase devem utilizar seus equivalentes kebab-case (delimitados por hífen):

const app = Vue.createApp({})

app.component('blog-post', {
  // camelCase no JavaScript
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
1
2
3
4
5
6
7
<!-- kebab-case no HTML -->
<blog-post post-title="olá!"></blog-post>
1
2

Novamente, caso você esteja usando templates String, esta limitação não se aplica.