【composition API】provide/inject

626 阅读1分钟

provide/inject可以穿过多层级组件进行传值,provide/inject与composition api一起使用,两者都只能在setup()当前活动实例期间调用。

Provide

在setup()中使用provide时,需要在vue中导出provide,我们可以根据需求定义每个provide的属性,provide函数允许定义该属性的名称和属性的值。

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

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

export default {
  components: {
    MyMarker
  },
  setup() {
    provide('location', 'North Pole')
    provide('geolocation', {
      longitude: 90,
      latitude: 135
    })
  }
}
</script>

Inject

在setup()中使用inject时,需要在vue中导出inject,inject函数有两个参数,一个是要注入的属性的名称,一个是默认值,为可选项。

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

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')

    return {
      userLocation,
      userGeolocation
    }
  }
}
</script>

Reactivity

为了使provide和inject之间有响应式,我们可以在提供者使用ref或者reactive这两个composition api实现关联。

<!-- 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('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)
  }
}
</script>

当提供者的任意属性发生变化,接收的组件也会自动更新。在使用provide和inject时,建议尽可能在提供方对响应式属性进行更改。但是,有时我们需要更新注入数据的组件内部的数据。在这种情况下,我们建议提供一种负责改变响应式属性的方法。官网例子:

<!-- 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('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }

    provide('location', location)
    provide('geolocation', geolocation)
    provide('updateLocation', updateLocation)
  }
}
</script>
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'
export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')
    const updateUserLocation = inject('updateLocation')

    return {
      userLocation,
      userGeolocation,
      updateUserLocation
    }
  }
}
</script>