likes
comments
collection
share

Vue3组件数据传输

作者站长头像
站长
· 阅读数 276

1.父子组件的数据传输

说明:此处的例子使用并不一定是最佳使用方式,仅为了验证数据的传输

父组件

<template>
  <p>++++++++++++++++++<b>调用子组件</b>+++++++++++++++++++++</p>
  <p>子组件调用父组件方法测试,子组件提交即可生成随机数 {{ random }}</p>
  <p>在调用的子组件定义ref</p>
  <hello-world :random="random" ref="greeting" @getRandom="getRandom" />
</template>

<script>
import HelloWorld from "../components/HelloWorld.vue";
import { ref, onMounted } from "vue";
export default {
  components: { HelloWorld },
  setup(props, ctx) {
    // **父组件获取子组件的数据**
    // const的值为上面子组件定义的ref
    const greeting = ref(null);

    onMounted(() => {
      // **父组件获取子组件的值**
      console.log(greeting.value.greeting);
      greeting.value.submitGreeting();
      // ++++++++end+++++++++++++++++
    });

    // **子组件获取父组件的值和方法
    // 父组件先定义函数 ==>生成随机数
    let random = ref(1);
    const getRandom = () => {
      random.value = Math.floor(Math.random() * 100);
    };

    return {
      random,
      greeting,
      getRandom,
    };
  },
};
</script>

子组件

// 主要验证vuex的使用, 和父子兄弟组件之间的交互
<template>
  <input
    type="text"
    name="greetings"
    v-model="greeting"
    style="margin-right: 20px"
  />
  <button @click="submitGreeting">提交Greeting</button>
</template>

<script>
import { ref } from "vue";
import { useStore } from "vuex";
export default {
  name: "HelloWorld",
  // **子组件获取父组件的值**
  props: {
    random: {
      type: Number,
    },
  },
  // **子组件获取父组件传入的方法**
  emits: ["getRandom"],
  setup(props, ctx) {
    const store = useStore();
    const greeting = ref("Hello");
    // 将值存入store
    const submitGreeting = () => {
      store.commit("submitGreeting", greeting.value);
      store.commit("increment");
      console.log("点击提交Greetings按钮,修改次数+1");
      // ++++++++++验证子组件调用父组件的方法++++++++
      // 通过emits传入的方法
      ctx.emit("getRandom");
      // ++++++++++++++++++end+++++++++++++++++++
    };

    // +++++++++++++验证父组件调用子组件的方法+++++++++++++
    // 将组件中的值暴露出去, 否则父组件中无法使用
    ctx.expose({ greeting, submitGreeting });
    // ++++++++++++++++++end+++++++++++++++++++

    return {
      greeting,
      submitGreeting,
    };
  },
};
</script>

跨组件的调用(provide和inject)

第一层组件

<template>
</template>

<script>
import { ref, provide } from "vue";
export default {
  setup(props, ctx) {
    // 生成随机数
    let random = ref(1);
    const getRandom = () => {
      random.value = Math.floor(Math.random() * 100);
    };
    // provide 和 reject 的使用
    provide("user", random);

    return {
      random,
    };
  },
};
</script>

跨组件

// 主要验证provide 和reject 的使用
<template>
  <div>我只是想试下provide 和 reject 怎么用 {{ user }}</div>
</template>
<script>
import { inject } from "vue";

export default {
  name: "Next",
  setup() {
    // provide传过来的值
    const user = inject("user");
    return {
      user,
    };
  },
};
</script>

事件总线

Vue3中去除了 on,off等事件,所以事件总线推荐使用外部库,此处使用mitt

先安装mittnpm install mitt --save

main.js

import { createApp } from "vue";
import App from "./App.vue";

// 使用第三方组件实现事件总线的功能
import mitt from "mitt";

const app = createApp(App);
app.mount("#app");
// 添加一个可以在应用的任何组件实例中访问的全局 property, 代替之前的Vue.prototype.
app.config.globalProperties.emitter = new mitt();

传输数据的组件

<script>
import { getCurrentInstance } from "vue";
export default {
  setup(props, ctx) {
    const { proxy } = getCurrentInstance();
    // 在使用的位置调用该方法,触发事件总线
    const emitBus = () => {
      // 传入一个方法
      proxy.emitter.emit("mittFn", () => {
        console.log("传入一个方法");
      });
      // 传入一个变量
      proxy.emitter.emit("mittData", "");
    };

  },
};
</script>

接收数据的组件

<script>
import {
  onMounted,
  getCurrentInstance,
  onBeforeUnmount,
} from "vue";

export default {
  setup() {
    const { proxy } = getCurrentInstance();
    // 接收数据
    onMounted(() => {
      proxy.emitter.on("mittFn", (fn) => {
        console.log("事件总线传入的方法:", fn());
      });

      proxy.emitter.on("mittData", (data) => {
        console.log("事件总线发布的数据:", data);
      });
    });
    // 删除事件总线
    onBeforeUnmount(() => {
      proxy.emitter.off("mittFn");
      proxy.emitter.off("mittData");
    });
  },
};
</script>