# refs de Template

Esta seção usa a sintaxe de componente single-file para exemplos de código

Este guia pressupõe que você já leu a Introdução à API de Composição e os Fundamentos da Reatividade. Leia lá primeiro se você for novo na API de Composição.

Ao usar a API de Composição, os conceitos de refs reativos e refs de template são unificados. Para obter uma referência a um elemento do template ou instância de componente, podemos declarar uma referência como de costume e retorná-la de setup():

<template>
  <div ref="root">Este é um elemento raiz</div>
</template>

<script>
  import { ref, onMounted } from 'vue'

  export default {
    setup() {
      const root = ref(null)

      onMounted(() => {
        // o elemento DOM será atribuído ao ref após a renderização inicial
        console.log(root.value) // <div>Este é um elemento raiz</div>
      })

      return {
        root
      }
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Aqui estamos expondo root no contexto de renderização e vinculando-o a div como sua referência via ref="root". No algoritmo de correção (patch) do DOM Virtual, se a chave ref de um VNode corresponder a uma referência no contexto de renderização, o elemento ou instância de componente correspondente do VNode será atribuído ao valor dessa referência. Isso é realizado durante o processo de montagem / patch do Virtual DOM, portanto, as referências do template só receberão valores atribuídos após a renderização inicial.

Referências usadas como refs de template se comportam como quaisquer outras refs: elas são reativas e podem ser passadas (ou retornadas) a funções de composição.

# Uso com JSX

export default {
  setup() {
    const root = ref(null)

    return () =>
      h('div', {
        ref: root
      })

    // com JSX
    return () => <div ref={root} />
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# Uso dentro de v-for

As refs de template da API de Composição não têm tratamento especial quando usadas dentro de v-for. Em vez disso, use a sintaxe de função nas refs para realizar um tratamento personalizado:

<template>
  <div v-for="(item, i) in list" :ref="el => { if (el) divs[i] = el }">
    {{ item }}
  </div>
</template>

<script>
  import { ref, reactive, onBeforeUpdate } from 'vue'

  export default {
    setup() {
      const list = reactive([1, 2, 3])
      const divs = ref([])

      // certifique-se de limpar as refs antes de cada atualização
      onBeforeUpdate(() => {
        divs.value = []
      })

      return {
        list,
        divs
      }
    }
  }
</script>
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

# Observando refs de Templates

Observar uma referência de template por alterações pode ser uma alternativa ao uso de gatilhos de ciclo de vida que foi demonstrado nos exemplos anteriores.

Mas uma diferença chave para os gatilhos do ciclo de vida é que os efeitos watch() e watchEffect() são executados antes do DOM ser montado ou atualizado, de modo que o ref de template ainda não foi atualizado quando o observador executa o efeito:

<template>
  <div ref="root">Este é um elemento raiz</div>
</template>

<script>
  import { ref, watchEffect } from 'vue'

  export default {
    setup() {
      const root = ref(null)

      watchEffect(() => {
        // Este efeito é executado antes que o DOM seja atualizado e, consequentemente,
        // o ref de template ainda não contém uma referência ao elemento.
        console.log(root.value) // => null
      })

      return {
        root
      }
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Portanto, observadores que usam refs de template devem ser definidos com a opção flush: 'post'. Isso executará o efeito depois do DOM ser atualizado e garantirá que o ref de template permaneça em sincronia com o DOM e faça referência ao elemento correto.

<template>
  <div ref="root">Este é um elemento raiz</div>
</template>

<script>
  import { ref, watchEffect } from 'vue'

  export default {
    setup() {
      const root = ref(null)

      watchEffect(() => {
        console.log(root.value) // => <div>Este é um elemento raiz</div>
      }, 
      {
        flush: 'post'
      })

      return {
        root
      }
    }
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24