Vue 3 combined provide / inject

Time:2021-6-30

Welcome to my official account, “life code“.

Combined supply and injection

In the previous chapter, we talked about the optional supply and injection, today we continue to talk about the combined supply and injection.

We can also use provide / inject in the composite API. Both can only be used on thesetup()Call during.

Imagine the scene

Suppose we rewrite the following code, which contains aTemplateMComponent, which uses the combined API forMyMarkerComponent provides the location of the user.

`<template>
  <MyMarker />
</template>
<script>
import MyMarker from ‘../components/MyMarker’
export default {
  components: {
    MyMarker
  },
  provide: {
    location: ‘North Pole’,
    geolocation: {
      longitude: 90,
      latitude: 135
    }
  }
}
</script>
`

The code for mymaker.vue is as follows:

`<template>
  <div>
    {{location}} – {{geolocation}}
  </div>
</template>
<!– src/components/MyMarker.vue –>
<script>
export default {
  inject: [‘location’, ‘geolocation’]
}
</script>
`

We can see the effect as follows:

Above we use the option type supply and injection, next we use the combined API to transform the above code.

Combined provider

staysetup()Used inprovideWe start withvueExplicit importprovidemethod. This enables us to callprovideTo define each property.

provideFunction allows you to define properties with two parameters:

  1. The name of the property(<String>Type)
  2. Value of property

useTemplateMComponent, the values we provide can be refactored as follows:

`<template>
  <MyMarker />
</template>
<script>
import MyMarker from ‘../components/MyMarker’
import {provide} from ‘vue’
export default {
  components: {
    MyMarker
  },
  setup() {
    provide(‘location’, ‘North Pole’)
    provide(‘geolocation’, {
      longitude: 90,
      latitude: 135
    })
  },
}
</script>
`

What we found out was thatprovideObject transformed intoprovide(key, value)The form of the function.

Combined object

staysetup()Used ininjectIt is also necessary tovueImport it explicitly. Once we do, we can call it to define how to expose it to our components.

injectThe function has two arguments:

  1. The name of the property to inject
  2. A default value(Optional)

useMyMarkerComponent, which can be refactored using the following code:

`<template>
  <div>{{ location }} – {{ geolocation }}</div>
</template>
<!– src/components/MyMarker.vue –>
<script>
import { inject } from ‘vue’
export default {
  name: ‘MyMarker’,
  setup() {
    const location = inject(‘location’)
    const geolocation = inject(‘geolocation’)
    return {
      location,
      geolocation
    }
  }
}
</script>
`

Let’s look at the effect again as follows:

Responsive

Add responsive

To increase the responsiveness between the supplied value and the injected value, we can use ref or reactive when providing the value.

useTemplateMComponent, our code can be updated as follows:

`<template>
  <MyMarker />
</template>
<script>
import MyMarker from ‘../components/MyMarker’
import {provide, ref, reactive} from ‘vue’
export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref(‘North Pole’)
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })
    provide(‘location’, location)
    provide(‘geolocation’, geolocation)
  },
}
</script>
`

Now, if there are any changes in these two properties,MyMarkerComponents will also be updated automatically!

Modify responsive property

When using responsive supply / injection values,It is recommended that, as far as possible, theProviderKeep any changes to the responsive property within

For example, if you need to change the user’s location, we’d betterTemplateMComponent.

`<template>
  <MyMarker />
</template>
<script>
import MyMarker from ‘../components/MyMarker’
import {provide, ref, reactive} from ‘vue’
export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref(‘North Pole’)
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })
    provide(‘location’, location)
    provide(‘geolocation’, geolocation)
    return {
      location
    }
  },
  methods: {
    updateLocation() {
      this.location = “hahaha”
    }
  }
}
</script>
`

However, sometimes we need to update the injected data inside the injected component. In this case, we propose to provide a method responsible for changing the responsive property.

`<template>
  <MyMarker />
</template>
<script>
import MyMarker from ‘../components/MyMarker’
import {provide, ref, reactive} from ‘vue’
export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref(‘North Pole’)
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })
    const updateLocation = () => {
      location.value = “hahaha”
    }
    provide(‘location’, location)
    provide(‘geolocation’, geolocation)
    provide(‘updateLocation’, updateLocation)
  },
}
</script>
`

`<template>
  <div>{{ location }} – {{ geolocation }}</div>
</template>
<!– src/components/MyMarker.vue –>
<script>
import { inject } from ‘vue’
export default {
  name: ‘MyMarker’,
  setup() {
    const location = inject(‘location’)
    const geolocation = inject(‘geolocation’)
    const updateLocation = inject(‘updateLocation’)
    return {
      location,
      geolocation,
      updateLocation
    }
  }
}
</script>
`

Finally, if you want to make sure that you passprovideThe data passed will not be changed by the injected component. We recommend using the property of the providerreadonly

`<template>
  <MyMarker />
</template>
<script>
import MyMarker from ‘../components/MyMarker’
import {provide, ref, reactive, readonly} from ‘vue’
export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref(‘North Pole’)
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })
    const updateLocation = () => {
      location.value = “hahaha”
    }
    provide(‘location’, readonly(location))
    provide(‘geolocation’, readonly(geolocation))
    provide(‘updateLocation’, updateLocation)
  },
}
</script>
`