# v-model
breaking

# Visão Geral

Olhando por cima o que mudou:

  • QUEBRA: Quando usado em componentes customizados, o nome padrão da propriedade e do evento do v-model mudaram:
    • prop: value -> modelValue;
    • event: input -> update:modelValue;
  • QUEBRA: O modificador .sync que existia no v-bind e a opção model de componentes foram substituídos pelo v-model com um argumento;
  • NOVO: Múltiplos vínculos do v-model no mesmo componente são possíveis agora;
  • NOVO: Adicionado a possibilidade de criar modificadores para o v-model.

Para mais informações, continue lendo!

# Introdução

Quando o Vue 2.0 foi lançado, a diretiva v-model exigia para os desenvolvedores sempre usar a propriedade value. E se os desenvolvedores precisassem usar uma propriedade diferente para um outro propósito, eles deveriam recorrer ao uso do v-bind.sync. Além disso, essa relação fixa entre v-model evalue levou à problemas com a forma como os elementos nativos e personalizados eram tratados.

Na versão 2.2, introduzimos a opção de componente model que permite ao componente personalizar a propriedade e o evento para usar no v-model. No entanto, isso ainda apenas permitia que um único v-model fosse usado no componente.

Com o Vue 3, a API para vinculação de dados bidirecional está sendo padronizada para reduzir a confusão e permitir aos desenvolvedores mais flexibilidade com a diretiva v-model.

# Sintaxe v2.x

Na v2.x, usando um v-model em um componente era equivalente a passar uma propriedade value e emitir um evento input:

<ChildComponent v-model="pageTitle" />

<!-- seria um atalho para: -->

<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
1
2
3
4
5

Se quiséssemos mudar os nomes da propriedade ou evento para algo diferente, precisaríamos adicionar uma opção model ao componente ChildComponent:

<!-- ParentComponent.vue -->

<ChildComponent v-model="pageTitle" />
1
2
3
// ChildComponent.vue

export default {
  model: {
    prop: 'title',
    event: 'change'
  },
  props: {
    // isso permite a utilização da propriedade `value` para um propósito diferente
    value: String,
    // utilizando `title` como uma propriedade que irá tomar o lugar do `value`
    title: {
      type: String,
      default: 'Título padrão'
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Então, o v-model nesse caso seria um atalho para:

<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
1

# Usando v-bind.sync

Em alguns casos, podemos precisar de uma "ligação bidirecional" para uma propriedade (às vezes além do v-model existente para uma propriedade diferente). Para fazer isso, recomendamos a emissão de eventos no padrão de update:myPropName. Por exemplo, para ChildComponent do exemplo anterior com a propriedade title, poderíamos comunicar a intenção de atribuir um novo valor com:

this.$emit('update:title', newValue)
1

Em seguida, o pai pode ouvir esse evento e atualizar uma propriedade de dados local, se quiser. Por exemplo:

<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
1

Por conveniência, tínhamos uma abreviatura para esse padrão com o modificador .sync:

<ChildComponent :title.sync="pageTitle" />
1

# Sintaxe v3.x

Na versão 3.x o v-model em um componente personalizado é equivalente a passar um prop modelValue e emitir um evento update:modelValue:

<ChildComponent v-model="pageTitle" />

<!-- seria um atalho para: -->

<ChildComponent
  :modelValue="pageTitle"
  @update:modelValue="pageTitle = $event"
/>
1
2
3
4
5
6
7
8

# Argumentos do v-model

Para alterar o nome de um modelo, em vez de uma opção de componente model, agora podemos passar um argumento parav-model:

<ChildComponent v-model:title="pageTitle" />

<!-- seria um atalho para: -->

<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
1
2
3
4
5

Anatomia do v-bind

Isso também serve como um substituto para o modificador .sync e nos permite ter vários v-models no componente personalizado.

<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />

<!-- seria um atalho para: -->

<ChildComponent
  :title="pageTitle"
  @update:title="pageTitle = $event"
  :content="pageContent"
  @update:content="pageContent = $event"
/>
1
2
3
4
5
6
7
8
9
10

# Modificadores do v-model

Além dos modificadores do v-model fixos já existentes na v2.x, como .trim, agora v3.x suporta modificadores personalizados:

<ChildComponent v-model.capitalize="pageTitle" />
1

Leia mais sobre modificadores do v-model customizados na seção Eventos Customizados.

# Estratégia de Migração

Nós recomendamos:

  • verificar seu código aonde utilizado o .sync e substituí-lo por v-model:

    <ChildComponent :title.sync="pageTitle" />
    
    <!-- substituir por -->
    
    <ChildComponent v-model:title="pageTitle" />
    
    1
    2
    3
    4
    5
  • para todos os v-models sem argumentos, certifique-se de alterar o nome das propriedades e eventos para modelValue e update:modelValue respectivamente

    <ChildComponent v-model="pageTitle" />
    
    1
    // ChildComponent.vue
    
    export default {
      props: {
        modelValue: String // anteriormente era `value: String`
      },
      emits: ['update:modelValue'],
      methods: {
        changePageTitle(title) {
          this.$emit('update:modelValue', title) // anteriormente era `this.$emit('input', title)`
        }
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

Sinalizadores na compilação de migração:

  • COMPONENT_V_MODEL
  • COMPILER_V_BIND_SYNC

# Próximos Passos

Para mais informações na nova sintaxe do v-model, veja: