# Prover e Injetar Dados

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

Este guia assume que você já leu as seções Prover e Injetar Dados, Introdução a API de Composição e Fundamentos de Reatividade.

Podemos prover e injetar dados com a API de Composição também. Ambos só podem ser chamados durante setup() com uma instância ativa atual.

# Exemplo de Cenário

Vamos supor que queremos reescrever o código a seguir, que contém um componente MyMap que provê um componente MyMarker com a localização do usuário, usando a API de Composição.

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  provide: {
    location: 'Polo Norte',
    geolocation: {
      longitude: 90,
      latitude: 135
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- src/components/MyMarker.vue -->
<script>
export default {
  inject: ['location', 'geolocation']
}
</script>
1
2
3
4
5
6

# Usando Provide

Ao usar provide no setup(), começamos importando explicitamente o método de vue. Isso nos permite definir cada propriedade com sua própria invocação de provide.

A função provide permite definir a propriedade por meio de dois parâmetros:

  1. O nome da propriedade (do tipo <String>); e
  2. O valor da propriedade.

Usando nosso componente MyMap, nossos valores providos podem ser refatorados da seguinte forma:







 






 
 
 
 
 
 
 



<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    provide('location', 'Polo Norte')
    provide('geolocation', {
      longitude: 90,
      latitude: 135
    })
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# Usando Inject

Ao usar inject no setup(), também precisamos importá-lo explicitamente de vue. Assim que fizermos isso, isso nos permitirá invocá-lo para definir como queremos expô-lo ao nosso componente.

A função inject leva dois parâmetros:

  1. O nome da propriedade a injetar; e
  2. Um valor padrão (Opcional).

Usando nosso componente MyMarker, podemos refatorá-lo com o seguinte código:



 


 
 
 
 
 
 
 
 
 



<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'O Universo')
    const userGeolocation = inject('geolocation')

    return {
      userLocation,
      userGeolocation
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Reatividade

# Adicionando Reatividade

Para adicionar reatividade entre os valores providos e injetados, podemos usar uma ref ou reactive ao prover um valor.

Usando nosso componente MyMap, nosso código pode ser atualizado da seguinte forma:







 







 
 
 
 
 
 
 
 




<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('Polo Norte')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)
  }
}
</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

Agora, se alguma coisa mudar em qualquer uma das propriedades, o componente MyMarker também será atualizado automaticamente!

# Mutando Propriedades Reativas

Ao usar dados providos e injetados reativos, é recomendado manter quaisquer mutações nas propriedades reativas dentro do provider sempre que possível.

Por exemplo, no caso de precisarmos alterar a localização do usuário, o ideal seria fazer isso dentro de nosso componente MyMap.




























 
 
 
 
 



<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('Polo Norte')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)

    return {
      location
    }
  },
  methods: {
    updateLocation() {
      this.location = 'Polo Sul'
    }
  }
}
</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
27
28
29
30
31
32
33
34

No entanto, há momentos em que precisamos atualizar os dados dentro do componente onde os dados são injetados. Nesse cenário, recomendamos prover um método que seja responsável por mutar a propriedade reativa.





















 
 
 



 




<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('Polo Norte')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'Polo Sul'
    }

    provide('location', location)
    provide('geolocation', geolocation)
    provide('updateLocation', updateLocation)
  }
}
</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
27
28
29
30








 




 





<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'O Universo')
    const userGeolocation = inject('geolocation')
    const updateUserLocation = inject('updateLocation')

    return {
      userLocation,
      userGeolocation,
      updateUserLocation
    }
  }
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Por fim, recomendamos o uso de readonly na propriedade provida, se você quiser garantir que os dados passados por provide não possam sofrer mutação pelo componente injetado.







 

















 
 





<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, readonly, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('Polo Norte')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'Polo Sul'
    }

    provide('location', readonly(location))
    provide('geolocation', readonly(geolocation))
    provide('updateLocation', updateLocation)
  }
}
</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
27
28
29
30