vue3中provide和inject使用。

在Vue 3中,provideinject API是一种非常强大的功能,用于在组件层级之间传递数据,特别是在处理深层嵌套组件时非常有用。它们允许开发者跨越多个组件层级直接传递数据,而不需要通过每个层级逐层传递props。

基本概念

  • provide:用于定义要提供给后代组件的数据或方法。
  • inject:用于在后代组件中接收从祖先组件提供的数据或方法。

使用方法

  1. 在祖先组件中提供数据(provide)

    你可以在祖先组件中使用provide来定义要共享的数据。这通常在setup函数中完成。

import { provide, ref } from 'vue';

export default {
  setup() {
    const sharedData = ref('some data');

    // 提供数据
    provide('key', sharedData);

    // ...
  }
}
  1. 在这个例子中,我们提供了一个名为key的数据,其值为sharedData

  2. 在后代组件中注入数据(inject)

    在需要接收数据的子孙组件中,你可以使用inject来接收这些数据。

import { inject } from 'vue';

export default {
  setup() {
    // 注入数据
    const sharedData = inject('key');

    // 使用sharedData
    // ...

    return {
      sharedData
    };
  }
}
  1. 在这个例子中,我们注入了之前由祖先组件提供的名为key的数据。

注意事项

  • 唯一键provideinject使用一个唯一的标识符(在上面的例子中是'key')来配对提供者和接收者。这个键可以是字符串或Symbol。

  • 响应性:如果你希望提供的数据是响应式的,你应该使用refreactive来创建这些数据。

  • 默认值inject函数接受第二个可选参数作为默认值,当无法找到提供的数据时将使用这个默认值。

  • 作用域provideinject主要用于跨组件通信,它们不应该被用来替代组件的正常props和events通信模式。

示例场景

假设你正在构建一个应用,其中有一个深层嵌套的组件结构,你需要在顶层组件中设置一个主题(如颜色主题),并且希望所有子组件都能访问到这个设置。使用provideinject可以轻松地实现这一功能,而不需要在每个中间组件中传递props。

provideinject的这种使用方式有助于保持组件接口的清洁和简单,同时提供一种强大的跨组件通信机制。

在Vue2.x中,provide和inject是单向数据流,即子组件通过inject获取父组件provid的变量,但是子组件修改后并不能反向影响到父组件。而在Vue3.x中,我们可以通过使用reactive和toRef将provide的数据变成响应式的,实现provide和inject的双向绑定。

// Parent组件
import { reactive, toRef } from 'vue';
export default {
  setup() {
    const state = reactive({ count: 0 });
    // 暴露出count及其响应式引用
    provide('count', { count: state.count, countRef: toRef(state, 'count') });
    return { state };
  },
};
// Child组件
import { inject } from 'vue';
export default {
  setup() {
    // inject暴露出来的对象包含count及其响应式引用
    const { count, countRef } = inject('count');
    function add() {
      countRef.value++;
    }
    return { count, add };
  },
};

高阶用法:

使用Symbol作为键为了防止键名冲突,特别是在大型项目或第三方库中,你可以使用Symbol作为提供和注入的键。
const SharedStateSymbol = Symbol();

export { SharedStateSymbol };

在提供者中:

import { provide, ref } from 'vue';
import { SharedStateSymbol } from './symbols';

export default {
  setup() {
    const sharedState = ref({ counter: 0 });

    provide(SharedStateSymbol, sharedState);

    // ...
  }
}

在注入者中:

import { inject } from 'vue';
import { SharedStateSymbol } from './symbols';

export default {
  setup() {
    const sharedState = inject(SharedStateSymbol);

    // ...

    return {
      sharedState
    };
  }
}

在组合函数中使用provide/inject

provideinject也可以在组合函数(Composition Functions)中使用,这使得你可以创建可重用的逻辑片段。

// useSharedState.js
import { provide, ref, inject } from 'vue';
const SharedStateSymbol = Symbol();

export function provideSharedState() {
  const sharedState = ref({ counter: 0 });
  provide(SharedStateSymbol, sharedState);
}

export function useSharedState() {
  const sharedState = inject(SharedStateSymbol);
  if (!sharedState) {
    throw new Error('No provided shared state!');
  }
  return sharedState;
}

配合TypeScript使用

当使用TypeScript时,你可以为提供和注入的数据提供类型注解,以增加类型安全性。

import { provide, inject, ref, Ref } from 'vue';

interface SharedState {
  counter: number;
}

const SharedStateSymbol: InjectionKey> = Symbol();

export default {
  setup() {
    const sharedState: Ref = ref({ counter: 0 });

    provide(SharedStateSymbol, sharedState);

    // ...
  }
}

// 在子组件中
export default {
  setup() {
    const sharedState = inject(SharedStateSymbol);

    if (!sharedState) {
      throw new Error('sharedState is not provided');
    }

    // ...

    return {
      sharedState
    };
  }
}

这些高阶用法能够让你更有效地在Vue应用中管理跨组件的状态和逻辑,同时保持代码的可维护性和可扩展性。

你可能感兴趣的:(vue3学习笔记,vue.js,前端,javascript)