# Provide / Inject

Подразумевается, что вы уже изучили и разобрались с разделами Provide / Inject, Введение в Composition API и Основы реактивности. Если нет — прочитайте их сначала.

Также можно использовать provide / inject и вместе с Composition API. Их можно вызывать только во время setup() с текущим активным экземпляром.

# Предыстория сценария использования

Предположим, что нужно переписать с использованием Composition API следующий код, где компонент MyMap предоставляет компоненту MyMarker текущее местоположение.

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

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

export default {
  components: {
    MyMarker
  },
  provide: {
    location: 'Северный полюс',
    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

# Использование Provide

Для использования provide в setup() сначала потребуется явно импортировать метод из vue. Это позволяет определить каждое свойство своим собственным вызовом provide.

Функция provide позволяет определить свойство с помощью двух параметров:

  1. Имя свойства (тип <String>)
  2. Значение свойства

В компоненте MyMap внедряемые значения можно переписать следующим образом:







 






 
 
 
 
 
 
 



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

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

export default {
  components: {
    MyMarker
  },
  setup() {
    provide('location', 'Северный полюс')
    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

# Использование Inject

Для использования inject в setup() также сначала потребуется явно импортировать метод из vue. После этого можно будет вызывать его, чтобы определить что требуется внедрить в компоненте.

Функция inject получает два параметра:

  1. Имя внедряемого свойства
  2. Значение по умолчанию (Опционально)

В компоненте MyMarker код можно переписать следующим образом:



 


 
 
 
 
 
 
 
 
 



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

export default {
  setup() {
    const userLocation = inject('location', 'Вселенная')
    const userGeolocation = inject('geolocation')

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

# Реактивность

# Добавление реактивности

Для добавления реактивности между предоставляемыми и внедряемыми значениями можно использовать ref или reactive при предоставлении значения.

Используя компонент 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('Северный полюс')
    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

Теперь, при изменении какого-либо из свойств, компонент MyMarker будет автоматически обновлён!

# Изменение реактивных свойств

При использовании реактивных значений для provide / inject рекомендуется сохранять любые мутации реактивных свойств внутри провайдера всегда когда это возможно.

Например, в случае необходимости изменить местоположение пользователя, идеально будет сделать это внутри компонента 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('Северный полюс')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

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

    return {
      location
    }
  },
  methods: {
    updateLocation() {
      this.location = 'Южный полюс'
    }
  }
}
</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

Однако бывает когда требуется обновить данные внутри компонента, в который внедряются данные. В таком случае рекомендуется предоставлять метод, который ответственен за изменение реактивного свойства.





















 
 
 



 




<!-- 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('Северный полюс')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'Южный полюс'
    }

    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', 'Вселенная')
    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

Наконец, рекомендуется использовать readonly на предоставляемых свойствах, если требуется гарантировать, что данные, передаваемые через provide не должны изменяться компонентом, в который внедряются.







 

















 
 





<!-- 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('Северный полюс')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'Южный полюс'
    }

    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

Deployed on Netlify.
Последнее обновление: 2021-01-31, 20:30:51 UTC