Skip to content

Interpretação de Lista ​

v-for ​

Nós podemos utilizar a diretiva v-for para interpretar uma lista de itens baseados em um arranjo. A diretiva v-for exije uma sintaxe especial na forma de item in items, onde items é o arranjo de dados de origem e o item é um pseudónimo para o elemento do arranjo sobre qual é interado:

js
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
js
data() {
  return {
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
template
<li v-for="item in items">
  {{ item.message }}
</li>

Dentro do escopo de v-for, as expressões do modelo de marcação tem acesso a todas propriedades do escopo do pai. Além disto, a v-for também suporta um segundo pseudónimo opcional para índice do item atual:

js
const parentMessage = ref('Parent')
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
js
data() {
  return {
    parentMessage: 'Parent',
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
template
<li v-for="(item, index) in items">
  {{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
  • Parent - 0 - Foo
  • Parent - 1 - Bar
  • O escopo de variável da v-for é similar ao seguinte código de JavaScript:

    js
    const parentMessage = 'Parent'
    const items = [
      /* ... */
    ]
    
    items.forEach((item, index) => {
      // tem acesso ao `parentMessage` do escopo externo 
      // mas `item` e `index` apenas estão disponíveis aqui
      console.log(parentMessage, item.message, index)
    })

    Repare como o valor de v-for corresponde a assinatura de função da resposta de forEach. Na realidade, podes utilizar a desestruturação no pseudónimo do item de v-for similar a desestruturação de argumentos de função:

    template
    <li v-for="{ message } in items">
      {{ message }}
    </li>
    
    <!-- with index alias -->
    <!-- com o pseudónimo de índice ("index") -->
    <li v-for="({ message }, index) in items">
      {{ message }} {{ index }}
    </li>

    Para v-for encaixados, o escopo também funciona de maneira similar as funções encaixadas. Cada escope de v-for em acesso aos escopos pai:

    template
    <li v-for="item in items">
      <span v-for="childItem in item.children">
        {{ item.message }} {{ childItem }}
      </span>
    </li>

    Tu também podes utilizar of como delimitador no lugar de in, para que esteja mais próximo da sintaxe da JavaScript para iteradores:

    template
    <div v-for="item of items"></div>

    v-for com um Objeto ​

    Tu também podes utilizar a v-for para iterar através das propriedades de um objeto. A ordem de iteração será baseada no resultado da chamada de Object.keys() sobre o objeto:

    js
    const myObject = reactive({
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    })
    js
    data() {
      return {
        myObject: {
          title: 'How to do lists in Vue',
          author: 'Jane Doe',
          publishedAt: '2016-04-10'
        }
      }
    }
    template
    <ul>
      <li v-for="value in myObject">
        {{ value }}
      </li>
    </ul>

    Tu também podes fornecer um segundo pseudónimo para o nome da propriedade (também conhecido como chave):

    template
    <li v-for="(value, key) in myObject">
      {{ key }}: {{ value }}
    </li>

    E um outro para o índice:

    template
    <li v-for="(value, key, index) in myObject">
      {{ index }}. {{ key }}: {{ value }}
    </li>

    v-for com um Limite ​

    A v-for também pode aceitar um inteiro. Neste caso repetirá o modelo de marcação que aquelas muitas vezes, baseado em um limite de 1...n.

    template
    <span v-for="n in 10">{{ n }}</span>

    Nota que aqui n começa com um valor inicial de 1 no lugar de 0.

    v-for no <template> ​

    Semelhante a v-if do modelo de marcação, também podes utilizar o marcador <template> para interpretar um bloco com vários elementos. Por exemplo:

    template
    <ul>
      <template v-for="item in items">
        <li>{{ item.msg }}</li>
        <li class="divider" role="presentation"></li>
      </template>
    </ul>

    v-for com v-if ​

    AVISO

    Não é recomendado utilizar v-if e v-for no mesmo elemento devido a precedência implicita. Consulte o guia de estilo para obter mais detalhes.

    Quando elas existem no mesmo nó, a v-if tem uma prioridade mais alta do que a v-for. Que significa que a condição v-if não terá acesso as variáveis do escope do v-for:

    template
    <!--
    Isto lançará um erro porque a propriedade "todo"
    não está definida na instância
    -->
    <li v-for="todo in todos" v-if="!todo.isComplete">
      {{ todo.name }}
    </li>

    Isto pode ser corrigido movendo v-for para um marcodor <template> de embrulho (que também é mais explicito):

    template
    <template v-for="todo in todos">
      <li v-if="!todo.isComplete">
        {{ todo.name }}
      </li>
    </template>

    Mantendo o Estado com key ​

    Quando a Vue está atualizando um lista de elementos interpretados com a v-for, por padrão ela utiliza uma estratégia de "remendar no lugar (in-place patch)". Se a ordem dos itens de dados mudou, no lugar de mover os elementos do DOM para corresponder a ordem dos itens, a Vue remendará cada elemento no lugar e certificar-se de que ela refleta o que deveria ser interpretado naquele índice particular.

    Este modo padrão é eficiente, mas só é adequando quando o resultado da interpretação da tua lista não depender do estado do componente filho ou do estado temporário do DOM (por exemplo, valores de entrada de formulário).

    Para dar a Vue uma sugestão para que ela possa rastreiar qualquer identidade do nó, e assim reutilizar e reorganizar os elementos existente, precisas fornecer um atributo key único para cada item:

    template
    <div v-for="item in items" :key="item.id">
      <!-- content -->
      <!-- conteúdo -->
    </div>

    Quando estiveres utilizando <template v-for>, o key deve ser colocado no contentor <template>:

    template
    <template v-for="todo in todos" :key="todo.name">
      <li>{{ todo.name }}</li>
    </template>

    NOTA

    Aqui key é um atributo especial sendo vinculado com a v-bind. Ela não deveria ser confundida com a variável chave (key) de propriedade quando estiveres utilizando a v-for com um objeto.

    É recomendado fornecer um atributo key com a v-for sempre que possível, a menos que o conteúdo de DOM iterado seja simples (por exemplo, não contém quaisquer componentes ou elementos de DOM com conteúdo), estás intencionalmente confiando no comportamento padrão para ganhos de desempenho.

    O vinculação de key aguarda por valores primitivos - por exemplo, sequências de caracteres e números. Não utilize objetos como chaves de v-for. Para utilização detalhada do atributo key, favor de consultar a documentação da API de key.

    v-for com um Componente ​

    Esta secção presume conhecimento de Componentes. Esteja livre para ignorá-la e voltar mais tarde.

    Tu podes utilizar a v-for diretamente sobre um componente, tal como qualquer elemento normal (não te esqueças de fornecer um key):

    template
    <MyComponent v-for="item in items" :key="item.id" />

    No entanto, isto não passará quaisquer dados automaticamente para o componente, porque os componentes têm seus próprios escopos isolados. Para passar o dado iterado para dentro do componente, também devemos utilizar as propriedades:

    template
    <MyComponent
      v-for="(item, index) in items"
      :item="item"
      :index="index"
      :key="item.id"
    />

    A razão para não injetar automaticamte o item para dentro do componente é porque isto torna o componente fortemente acoplado à como a v-for funciona. Ser explicito a respeito de onde os teus dados vem torna o componente reutilizável em outras situações.

    Consulte este exemplo de uma lista de afazeres simples para veres como interpretar uma lista de componentes utilizando a v-for, passando diferentes dados para cada instância.

    Consulte este exemplo de uma lista de afazeres simples para veres como interpretar uma lista de componentes utilizando a v-for, passando diferentes dados para cada instância.

    Deteção de Mudança de Arranjo ​

    Métodos de Mutação ​

    A Vue é capaz de detetar quando métodos de mutação de um arranjo reativo são chamados e aciona as atualizações necessárias. Estes métodos de mutação são:

    • push()
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()

    Substituindo um Arranjo ​

    Os métodos de mutação, como o nome sugere, alteram o arranjo original sobre o qual eles são chamados. Em comparação, também existem métodos que não realizam mutação, por exemplo, filter(), concat() e slice(), que não alteram o arranjo original mas sempre retornam um arranjo novo. Quando estivermos trabalhando como métodos que não realizam mutação, devemos substituir o arranjo antigo com o arranjo novo:

    js
    // `items` é uma referência com valor de arranjo
    items.value = items.value.filter((item) => item.message.match(/Foo/))
    js
    this.items = this.items.filter((item) => item.message.match(/Foo/))

    Tu podes achar que isto fará a Vue deixar fora o DOM existente e reinterpretar a lista inteira - felizmente, este não é o caso. A Vue implementa algumas heurísticas inteligentes para maximizar a reutilização do elemento do DOM, assim substituir um arranjo com um outro arranjo contendo objetos que se sobrepõem é uma operação muito eficiente.

    Exibindo Resultados Filtrados ou Organizados ​

    Algumas vezes queremos exibir uma versão filtrada ou organizada de um arranjo sem alterar ou redefinir os dados originais. Neste caso, podes criar uma propriedade computada que retorna o arranjo filtrado ou organizado.

    Por exemplo:

    js
    const numbers = ref([1, 2, 3, 4, 5])
    
    const evenNumbers = computed(() => {
      return numbers.value.filter((n) => n % 2 === 0)
    })
    js
    data() {
      return {
        numbers: [1, 2, 3, 4, 5]
      }
    },
    computed: {
      evenNumbers() {
        return this.numbers.filter(n => n % 2 === 0)
      }
    }
    template
    <li v-for="n in evenNumbers">{{ n }}</li>

    Em situações onde as propriedades computadas não são viáveis (por exemplo, dentro de laços v-for encaixados), podes utilizar um método:

    js
    const sets = ref([
      [1, 2, 3, 4, 5],
      [6, 7, 8, 9, 10]
    ])
    
    function even(numbers) {
      return numbers.filter((number) => number % 2 === 0)
    }
    js
    data() {
      return {
        sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
      }
    },
    methods: {
      even(numbers) {
        return numbers.filter(number => number % 2 === 0)
      }
    }
    template
    <ul v-for="numbers in sets">
      <li v-for="n in even(numbers)">{{ n }}</li>
    </ul>

    Tenha cuidado com reverse() e sort() dentro de uma propriedade computada! Estes dois métodos alterarão o arranjo original, o que deve ser evitado nos recuperadores computados. Crie uma copia do arranjo original antes de chamar estes métodos:

    diff
    - return numbers.reverse()
    + return [...numbers].reverse()
    Interpretação de Lista has loaded