五、Vue3.x+Element Plus项目Demo引入自定义组件并实现祖孙/父子组件响应式传参

郁子原创大约 3 分钟约 1024 字项目搭建Vue3Vite3Element Plus依赖注入

前言

学习 Vite 和 Vue3 并搭建项目 Demo,主要目的是搭项目,对于新手直接跟着操作就可以把项目搭起来,借这个机会自己尝试写写博客,希望对大家有帮助。

参考链接

(一)准备祖孙/父子组件

使用 Element Plus 的抽屉组件,实现父组件按钮控制子组件抽屉打开的功能。

1.祖/父组件 src/components/HelloWorld.vue

<template>
  <!-- 打开抽屉 -->
  <el-button @click="handleOpenChildrenDrawer" type="success" style="width: 100%; margin: 20px auto">{{ t("button.openDrawer") }}</el-button>
</template>

<script setup>
  import { ref } from "vue";

  /**
   * 自定义组件
   */
  const isDrawerOpen = ref(false);
  const handleOpenChildrenDrawer = () => {
    isDrawerOpen.value = true;
  };
</script>

2.孙/子组件 src/components/SideDrawer.vue

<template>
  <el-drawer v-model="drawer" :before-close="handleClose" title="I am the title" direction="rtl">
    <span>Hi, there!</span>
  </el-drawer>
</template>

<script setup>
  import { ref } from "vue";

  const drawer = ref(true);
  const handleClose = (done) => {
    ElMessage("Drawer closed.");
    done();
  };
</script>

(二)祖/父组件中引入孙/子组件

1.普通 <script> 写法

1)引入组件

import SideDrawer from "./SideDrawer.vue";

2)挂载组件

export default defineComponent({
  components: {
    SideDrawer,
    "v-sidedrawer": SideDrawer,
    "side-drawer": SideDrawer,
  },
  setup() {},
});

有三种写法:

  • 直接挂载:SideDrawer
  • 使用别名:"v-sidedrawer": SideDrawer
  • 横杠连接:"side-drawer": SideDrawer

3)展示组件

<template>
  <SideDrawer></SideDrawer>
  <v-sidedrawer></v-sidedrawer>
  <side-drawer></side-drawer>
</template>

有三种写法,分别对应三种挂载的不同写法:

  • 直接挂载:<SideDrawer></SideDrawer>
  • 使用别名:<v-sidedrawer></v-sidedrawer>
  • 横杠连接:<side-drawer></side-drawer>

2.使用 <script setup> 语法糖

<template>
  <SideDrawer></SideDrawer>
</template>

<script setup>
  import SideDrawer from "./SideDrawer.vue";
</script>

直接 import 引入即可在模板中使用,无需挂载。

(三)祖孙/父子组件响应式传参

1.使用 provide 传递参数

  • 通常父子组件间传参直接使用 prop 最简便,也可使用 provide/inject
  • 祖孙组件间使用 provide/inject 传参。
  • provide/inject 本身传递数据是不具有响应性的。
    • provide 传递的数据是 refreactive 对象时,子组件 inject 的数据才具有响应性。
    • 即当祖/父组件修改该数据时,孙/子组件才会接收到修改后的数据。
import { onMounted, ref, provide } from "vue";

// 提供响应式的值
provide("isDrawerOpen", isDrawerOpen);

2.使用 inject 接收参数

import { inject } from "vue";

// 注入一个值,若为空则使用提供的默认值
const drawer = inject("isDrawerOpen", false);

(四)相关知识点总结

注意

provide/inject 只能在 setup() 中使用,使用前需要从 vue 中 import 进来。

  • provide 函数有两个参数:
    • name ( 类型)
    • value
  • inject 函数有两个参数:
    • 要 inject 的 property 的 name
    • 默认值 (可选)

1.调用 provide 函数,将值传给自定义组件(子组件)

provide('数据名称', 要传递的数据)

provide("location", "North Pole");
provide("geolocation", {
  longitude: 90,
  latitude: 135,
});

2.调用 inject 函数,通过指定的数据名称获取到父组件共享的数据

const customVal = inject("customVal")

const userLocation = inject("location", "The Universe");
const userGeolocation = inject("geolocation");

return {
  userLocation,
  userGeolocation,
};

3.使传递的数据响应式更新

为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 或 reactive。

const location = ref("North Pole");
const geolocation = reactive({
  longitude: 90,
  latitude: 135,
});

provide("location", location);
provide("geolocation", geolocation);

4.同组件中,数据 A 的值挂靠在数据 B 的更新上

使用 vue 提供的计算属性 computed ,Vue 知道数据 B 依赖于数据 A,所以当数据 A 更新时,数据 B 也会更新。

参考文档:vue3 动态的改变样式 - 一封未寄出的信 - 博客园open in new window

上次编辑于: